Subversion Repositories Kolibri OS

Rev

Rev 2678 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;
  2. ;   Phoenix Game. Based on ASCL Library
  3. ;
  4.  
  5. ;**********************************************************************
  6.    use32
  7.    org    0x0
  8.    db     'MENUET01'              ; 8 byte id
  9.    dd     0x01                    ; header version
  10.    dd     START                   ; start of code
  11.    dd     IM_END                  ; size of image
  12.    dd     I_END                   ; memory for app
  13.    dd     I_END                   ; esp stack position
  14.    dd     0x0 , 0x0               ; I_Param , I_Icon
  15. ;**********************************************************************
  16.  
  17. include 'lang.inc'    ; for SVN 'lang.inc'
  18. include '../../../macros.inc'  ; for SVN '..\..\..\macros.inc;'
  19. include 'ascl.inc'         ; main
  20. include 'ascgl.inc'        ; graphics
  21. include 'ascpoal.inc'      ; processing object array
  22. include 'ascgml.inc'       ; game library for collision detection
  23.  
  24. ; debug flags
  25. keyboard_debug=0     ; Set to 1 to view all keyboard keys state in game
  26. light_space=0        ; May used for check canvas position in window
  27. debug_scenario=0     ; May used for fast test of gameplay
  28. stack_leak_debug=0   ; Show stack size on screen
  29. debug_mode=1         ; Support keys:
  30. ; A - set player hp = 10000. Make player ship undestructible
  31. ; E - player hp / 2
  32. ; W - view final screen after game begin
  33.  
  34. screen_w equ 640
  35. screen_h equ 440
  36. ;screen_w equ 1014
  37. ;screen_h equ 739
  38.  
  39. ; Define special colors
  40. cl_DarkRed equ 0x990000
  41. cl_Orange  equ 0xbbbb00
  42.  
  43. ; Define objects type id
  44. EmptyObject  equ 0
  45. ; This numbers not possible for modify because draw_objects:
  46. BlueWarShip  equ 1
  47. GreenWarShip equ 2
  48. Asteroid     equ 3
  49. Box          equ 4
  50.  
  51. Laser        equ 1
  52. Plasma       equ 2
  53. StaticPlasma equ 3
  54.  
  55. ;**************************************************************
  56. ;                      Start of programm
  57. ;**************************************************************
  58.  
  59. START:                          ; start of execution
  60.  
  61.    max_particles = 400
  62.    particle_size = 20
  63.  
  64.    mov [particles],dword max_particles
  65.    mov [particles+4],dword particle_size
  66.  
  67.    max_objects = 100
  68.    object_size = 20
  69.  
  70.    mov [objects],dword max_objects
  71.    mov [objects+4],dword object_size
  72.  
  73.    keyboard_set_input_mode 1  ; 0 - ASCII; 1 - scancodes;
  74.  
  75.    ;giftoimg gif_file_area2,canvas
  76.    giftoimg gif_file_area,objects_image
  77.  
  78.    ; load sprites
  79.    mov cl,9      ; cl - counter
  80.    xor esi,esi   ; esi = 0
  81.    lea edi,[ship_img]  ; address of first sprite
  82. load_sprite:
  83.    pushad
  84.    getimg objects_image,esi,0,32,32,edi
  85.    popad
  86.    add edi,8+32*32*3   ; incrase offest of image data
  87.    add esi,32          ; incrase x position
  88.    dec cl
  89.    jnz load_sprite
  90.  
  91. set_main_menu:
  92.    mov ebx,-1       ; at start event_mode = -1
  93.    lea ecx,[draw_main_window]
  94.    lea edx,[menu_keyboard]
  95. set_draw_proc:
  96.    ; assembler extract command ; for use only bl
  97.    mov [event_mode],ebx
  98.    mov [draw_proc],ecx
  99.    mov [keyboard_proc],edx
  100.    ; at first draw window
  101. main_menu:
  102. redraw_event:     ; redraw event appears if user move, show/hide window
  103.    call draw_window
  104. no_event:
  105.    call [draw_proc]  ; no event no requre draw_window for no flickering
  106. if stack_leak_debug = 1
  107.    ; stack memory leak debug
  108.    lea ebp,[I_END]
  109.    sub ebp,esp
  110.    outcount ebp,10,30,cl_Green,5*65536
  111. end if
  112. menu_loop:
  113.    ;wait_event redraw_event,keyboard_event,button_event
  114.    mov eax,10   ; wait event
  115.    mov ebx,[event_mode]
  116.    cmp ebx,-1   ; ebx delay for mcall 23
  117.    je wait_ev
  118.    mov eax,23   ; time event
  119. wait_ev:
  120.    mcall
  121.    dec eax
  122.    js  no_event
  123.    jz  redraw_event
  124.    dec eax
  125.    jz  keyboard_event
  126.    dec eax
  127.    jz  button_event
  128.    jmp menu_loop  ; if unknown event, skip it
  129.  
  130. keyboard_event:   ; keyboard event if user press button
  131.    call [keyboard_proc]
  132.    jmp  menu_loop
  133. button_event:
  134.    window_get_button
  135.    cmp ah,1       ; if button id=1 (Red X of window) then close app
  136.    je  close_app
  137.    cmp ah,2       ; if button id=2 then close app
  138.    je  close_app
  139.    cmp ah,3       ; if button id=3 then start game
  140.    je  start_game
  141.    cmp ah,4       ; if button id=3 then show help menu
  142.    je  set_help_window  ; jmp with redraw window
  143.    cmp ah,5       ; if button id=5 then back to main menu
  144.    je  set_main_menu    ; jmp with redraw window
  145.    cmp ah,6
  146.    je  next_level  ; run next level
  147.    cmp ah,7
  148.    je  restart_lev ; restart level from gameover
  149.    cmp ah,9
  150.    je  set_game_window  ; back to game from menu
  151.    jmp menu_loop
  152.  
  153. close_app:
  154.    mov  eax,-1          ; close this program
  155.    mcall
  156.  
  157. menu_keyboard:
  158.    ; nothing do
  159.    window_get_key
  160.    ret
  161.  
  162. ;***********************
  163. ;   Main screen menu
  164. ;***********************
  165.  
  166. draw_main_window:
  167.    draw_label 160,160,'Phoenix',cl_Red+font_size_x8
  168.    draw_button 3,300,320,60,14,'START',cl_DarkRed,cl_Yellow
  169.    draw_button 4,300,340,60,14,'HELP',cl_DarkRed,cl_Yellow
  170.    draw_button 2,300,360,60,14,'EXIT',cl_DarkRed,cl_Yellow
  171.    ret
  172.  
  173. ;**********************
  174. ;  End level process
  175. ;**********************
  176.  
  177. set_end_level_window_from_call:
  178.    add esp,4    ; remove call address from stack
  179. set_end_level_window:
  180.    lea edx,[menu_keyboard]
  181.    mov ebx,-1
  182.    lea ecx,[draw_end_level_window]
  183.    jmp set_draw_proc
  184.  
  185. draw_end_level_window:
  186.    draw_frect 170,130,300,190,cl_Grey
  187.    draw_label 280,150,'LEVEL COMPLETE',cl_Black
  188.    draw_button 2,180,300,80,14,'EXIT',cl_DarkRed,cl_Black
  189.    draw_button 5,280,300,80,14,'<MENU>',cl_DarkRed,cl_Black
  190.    draw_button 6,380,300,80,14,'NEXT >',cl_DarkRed,cl_Black
  191.  
  192.    draw_image 180,170,bwarship_img
  193.    draw_number [bships_destroyed],240,185,cl_Blue,3*65536
  194.  
  195.    draw_image 180,210,gwarship_img
  196.    draw_number [gships_destroyed],240,225,cl_Green,3*65536
  197.  
  198.    draw_image 180,250,box_img
  199.    draw_number [boxes_taken],240,265,cl_Orange,3*65536
  200.    ret
  201.  
  202. ;**********************
  203. ;  Game Over process
  204. ;**********************
  205.  
  206. restart_lev:
  207.    mov [next_wave_timer],0  ; Reset new wave timer
  208. prevpart:
  209.    call get_wave_info_offset
  210.    xor eax,eax
  211.    mov ax,[ebp]
  212.    dec eax                  ; If eax = 0 then start of level finded
  213.    jz  reset_all_varibles_and_restart_level
  214.    dec [level_wave]
  215.    jmp prevpart
  216.  
  217. set_game_over_window_from_call:
  218.    add esp,4
  219. set_game_over_window:
  220.    lea edx,[menu_keyboard]
  221.    mov ebx,-1
  222.    lea ecx,[draw_game_over_window]
  223.    jmp set_draw_proc
  224.  
  225. draw_game_over_window:
  226.    draw_frect 170,160,300,120,cl_Grey
  227.    draw_label 292,200,'GAME OVER',cl_Black
  228.    draw_button 2,180,260,80,14,'EXIT',cl_DarkRed,cl_Black
  229.    draw_button 5,280,260,80,14,'MENU',cl_DarkRed,cl_Black
  230.    draw_button 7,380,260,80,14,'RESTART',cl_DarkRed,cl_Black
  231.    ret
  232.  
  233. ;***********************
  234. ;    Main game loop
  235. ;***********************
  236.  
  237. next_level:
  238.    mov [next_wave_timer],0 ; Reset next wave timer
  239.    inc [level_wave]        ; Next wave
  240. start_game:
  241.    ; Set canvas size before logo is showed
  242.    image_set_size canvas,screen_w,screen_h
  243.  
  244. ; Clear all, and prepeare varibles before start
  245. reset_all_varibles_and_restart_level:
  246.  
  247.    ; Clear objects arrays
  248.    mov eax,0
  249.    cld
  250.    mov edi,particles+8
  251.    mov ecx,max_particles*particle_size/4
  252.    rep stosd
  253.    mov edi,objects+8
  254.    mov ecx,max_objects*object_size/4
  255.    rep stosd
  256.  
  257.    ; Reset keyboard state array
  258.    clear_buffer keymap, 128, 0
  259.  
  260.    ; Reset player ship state
  261.    mov [player_hp],100
  262.    mov [shipx],screen_w/2-16 ; Player ship x start position
  263.    mov [shipy],screen_h-40   ; Player ship y start position
  264.    mov [laser_shoots],1000   ; Laser projectiles at start
  265.    mov [plasma_shoots],500   ; Plasma projectiles at start
  266.  
  267.    ; Reset counters and gun charge values
  268.    xor eax,eax
  269.    mov [boxes_taken],eax
  270.    mov [gships_destroyed],eax
  271.    mov [bships_destroyed],eax
  272.    mov [laser_charge],eax
  273.    mov [plasma_charge],eax
  274.  
  275. set_game_window:
  276.    lea edx,[ingame_keyboard]
  277.    lea ecx,[draw_game_window]
  278.    mov ebx,2          ; time_event ebx = 2 ms
  279.    jmp set_draw_proc
  280.  
  281. draw_game_window:
  282.    draw_image 5,24,canvas
  283.  
  284.    xor eax,eax               ; Use eax as zero for compare
  285.    cmp [pause_on],eax        ; If pause = 0 nothing do
  286.    je no_pause
  287.    ret
  288. no_pause:
  289.  
  290.    cmp [player_hp],eax       ; If player_hp < 0 game over
  291.    jl  set_game_over_window_from_call
  292.  
  293.    cmp [laser_charge],eax
  294.    je  no_dec_laser_charge
  295.    dec dword [laser_charge]  ; If laser_charge > 0 decrase it
  296. no_dec_laser_charge:
  297.    cmp [plasma_charge],eax
  298.    je  no_dec_plasma_charge
  299.    dec dword [plasma_charge] ; If plasma_charge > 0 decrase it
  300. no_dec_plasma_charge:
  301.  
  302.    ; new wave test
  303.    inc dword [next_wave_timer]
  304.    call get_wave_info_offset
  305.    mov ax,[ebp]        ; [ebp] = time to activate string
  306.    cwde                ; extend ax to eax
  307.    cmp [next_wave_timer],eax
  308.    jne no_next_wave
  309.  
  310. add_new_wave_of_objects:
  311.    mov cl,[ebp+4+0]    ; cl = count of ships
  312.    mov ch,GreenWarShip ; ch = type of object
  313.    mov ebx,0x09040302  ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel]
  314.    call add_objects    ; add objects
  315.  
  316.    mov cl,[ebp+4+1]    ; cl = count of ships
  317.    mov ch,BlueWarShip  ; ch = type of object
  318.    mov ebx,0x03010306  ; ebx = random ranges : x = -1..1 y = -6..-4
  319.    call add_objects    ; add objects
  320.  
  321.    mov cl,[ebp+4+2]    ; cl = count of asteroids
  322.    mov ch,Asteroid     ; ch = type of object
  323.    mov ebx,0x05020502  ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel]
  324.    call add_objects    ; add objects
  325.  
  326.    mov cl,[ebp+4+3]    ; cl = count of boxes
  327.    mov ch,Box          ; ch = type of object
  328.    mov ebx,0x05020401  ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel]
  329.    call add_objects    ; add objects
  330.  
  331.    mov [next_wave_timer],0 ; Reset next wave timer
  332.    inc [level_wave]        ; Next wave
  333. no_next_wave:
  334.  
  335.    ; Calculate all active objects on screen
  336.    xor eax,eax           ; Use eax as zero
  337.    mov [objects_num],eax
  338.    array_processing objects,endtest ; ar_proc not modify eax, ebx
  339.    xor eax,eax           ; Use eax as zero
  340.    cmp [objects_num],eax ; If [objects_num] != 0, level is not complete
  341.    jnz level_not_complete
  342.  
  343.    call get_wave_info_offset
  344.    mov ax,[ebp+2]  ; ax = maxyrange
  345.    cwde            ; extend ax to eax
  346.    xor ebx,ebx     ; Use ebx as zero for compare
  347.    cmp eax,ebx     ; If [ebp+2] of level = 0, this is end of level
  348.    je  set_end_level_window_from_call  ; Show player score
  349.    dec ebx         ; Use ebx as -1 for compare
  350.    cmp eax,ebx
  351.    je  set_final_screen_window_from_call ; Show final animation
  352. level_not_complete:
  353.  
  354. no_end_lev:
  355.  
  356. ; Key state processing
  357.    cmp byte [keymap+key_Right],0
  358.    je  no_key_right
  359.    add dword [shipx],6
  360. no_key_right:
  361.    cmp byte [keymap+key_Left],0
  362.    je  no_key_left
  363.    sub dword [shipx],6
  364. no_key_left:
  365.    cmp byte [keymap+key_Space],0
  366.    je  no_key_lshoot
  367.    call try_to_make_laser_shoot
  368.    ;call try_to_make_plasma_shoot
  369. no_key_lshoot:
  370.    cmp byte [keymap+key_Up],0
  371.    je  no_key_pshoot
  372.    ;call try_to_make_plasma_nuke
  373.    call try_to_make_plasma_shoot
  374. no_key_pshoot:
  375.    cmp byte [keymap+key_Down],0
  376.    je  no_key_pnuke
  377.    call try_to_make_plasma_nuke
  378.    ;call try_to_make_laser_shoot
  379. no_key_pnuke:
  380.  
  381. ; Ship position correction (clamp macro)
  382.    cmp [shipx],5
  383.    jnl @f
  384.    mov [shipx],5
  385. @@:
  386.    cmp [shipx],screen_w-32-5
  387.    jng @f
  388.    mov [shipx],screen_w-32-5
  389. @@:
  390.  
  391.    mov al,7
  392. if light_space = 1
  393.    mov al,255
  394. end if
  395.    clear_buffer canvas+8,canvas_end-canvas-8,al
  396.  
  397.    compmas objects,particles,objects_and_particles_hit_handling
  398.    ; move objects and particles
  399.    array_processing objects,move_objects
  400.    array_processing particles,move_particles
  401.    ; remove particles out of screen
  402.    array_processing particles,remove_outofscr_particles
  403.    ; objects and particles collision test
  404.    array_processing objects,player_and_objects_collision_handling
  405.    array_processing particles,player_and_particles_collision_handling
  406.    ; draw objects and particles
  407.    array_processing objects,draw_objects
  408.    array_processing particles,draw_particles
  409.    ; draw player ship
  410.    image_draw_acimage canvas,ship_img,[shipx],[shipy],cl_Black
  411.  
  412.    ; Draw info indicators
  413.    draw_frect 150,5,64,5,cl_Black
  414.    mov eax,[plasma_charge]
  415.    sub eax,256
  416.    neg eax
  417.    shr eax,2
  418.    draw_frect 150,5,eax,5,cl_Cyan
  419.  
  420.    draw_frect 150,12,64,5,cl_Black
  421.    mov eax,[laser_charge]
  422.    sub eax,8
  423.    neg eax
  424.    shl eax,3
  425.    draw_frect 150,12,eax,5,cl_Yellow
  426.  
  427.    draw_frect 220,2,6*5+2 ,9,cl_Grey
  428.    draw_number [plasma_shoots],221,3,cl_Cyan,5*65536
  429.    draw_frect 220,11,6*5+2 ,9,cl_Grey
  430.    draw_number [laser_shoots],221,12,cl_Yellow,5*65536
  431.  
  432.    draw_frect 280,6,6*5+2 ,9,cl_Grey
  433.    draw_number [gships_destroyed],281,7,cl_Green,5*65536
  434.    draw_frect 320,6,6*5+2 ,9,cl_Grey
  435.    draw_number [bships_destroyed],321,7,cl_Blue,5*65536
  436.    draw_frect 360,6,6*5+2 ,9,cl_Grey
  437.    draw_number [boxes_taken],361,7,0xffaa00,5*65536
  438.  
  439.    ; number of objects in scene
  440.    draw_frect 400,2,6*5+2 ,9,cl_Grey
  441.    draw_number [objects_num],401,2,cl_Lime,5*65536
  442.  
  443.    draw_frect 400,11,6*5+2 ,9,cl_Grey
  444.    draw_number [player_hp],401,12,cl_Red,5*65536
  445.  
  446.    draw_frect 450,11,6*5+2 ,9,cl_Grey
  447.    draw_number [score],451,12,cl_Yellow,5*65536 ;+hide_zeros
  448.  
  449.    ; print keyboard keys state as string for debug
  450. if keyboard_debug = 1
  451.    mov ebx,10*65536+40
  452.    mov edx,keymap
  453.    mov esi,128
  454.    mov ecx,cl_White
  455.    mov eax,4
  456.    mcall
  457. end if
  458.    ret
  459.  
  460. ; Proc for calculate active objects on screen
  461. ; eax - empty object type = 0
  462. endtest:
  463.    xor eax,eax
  464.    cmp dword [edi+8],eax  ; object is empty ?
  465.    je  is_free
  466.    inc [objects_num]
  467. is_free:
  468.    ret
  469.  
  470. ; Proc for get offest to current level wave information
  471. get_wave_info_offset:
  472.    mov ebp,[level_wave]
  473.    shl ebp,3           ; ebp = ebp*8; 8 - lenght of one string in levels array
  474.    add ebp,levels      ; ebp = offset to string in levels array
  475.    ret
  476.  
  477. ; time_bwns - time before next wave start
  478. ; yrmax - y random position maximum value
  479. macro objects_wave time_bnws, yrmax, gships, bships, asteroids, boxes{
  480.    dw time_bnws, yrmax
  481.    db gships, bships, asteroids, boxes
  482. }
  483.  
  484. level_wave dd 0
  485. ; this array may optimized
  486. levels:
  487. ; for game not ended at start, each level must have objects set at start (1)
  488.    ; test pattern
  489. if debug_scenario = 1
  490.    ; two levels for debug game
  491.    objects_wave   1,   10,  1,  2,  4,  8   ; objset at start
  492.    objects_wave   0,    0,  0,  0,  0,  0
  493.    objects_wave   1,   10,  3,  3,  3,  3   ; objset at start
  494.    objects_wave   0,   -1,  0,  0,  0,  0
  495. else
  496.    ; level 1
  497.    objects_wave   1, 4000,  3, 10, 10,  0    ; objset at start
  498.    objects_wave 800, 2000,  5,  3,  5,  3
  499.    objects_wave 400, 2000,  3,  7,  5,  3
  500.    objects_wave 400,  800,  3,  5,  3,  0
  501.    objects_wave   0,    0,  0,  0,  0,  0    ; end of level
  502.    ; level 2
  503.    objects_wave   1, 4000, 10, 40,  0,  8    ; objset at start
  504.    objects_wave 400, 4000, 10, 10, 20,  6
  505.    objects_wave 400, 2000,  0, 20, 10,  2
  506.    objects_wave 400,  400, 10, 10, 20,  0
  507.    objects_wave   0,    0,  0,  0,  0,  0    ; end of game
  508.    ; level 3
  509.    objects_wave   1,  800,  0,  0,  5,  5   ; objset at start
  510.    objects_wave 500, 2000,  4, 20, 30,  0
  511.    objects_wave 500, 2000,  4, 20,  0,  8
  512.    objects_wave 500, 2000, 10,  0,  0,  4
  513.    objects_wave 500, 4000,  0, 30,  0,  0
  514.    objects_wave 400,  400,  3,  5, 15,  0
  515.    objects_wave 400,  400,  0,  0, 10,  0
  516.    objects_wave   0,   -1,  0,  0,  0,  0    ; end of level
  517. end if
  518.  
  519. ;***********************************
  520. ;         In game keyboard
  521. ;***********************************
  522.  
  523. ingame_keyboard:
  524.    window_get_key  ; read key (eax=2)
  525.    cmp al,0
  526.    jne this_is_hotkey
  527.    ; ah - contain scan code, al = 0
  528.    shl eax,16
  529.    shr eax,24      ; equal shr eax,8 + and eax,0x0FF
  530.    ; eax - contain scan code
  531.  
  532.    cmp al,key_P+128
  533.    jne not_P_key_up_scan_code
  534.    not [pause_on]
  535. not_P_key_up_scan_code:
  536.  
  537. if debug_mode = 1
  538.    cmp al,key_E    ; player hp = player hp / 2
  539.    jne no_hp_test
  540.    shr [player_hp],1
  541. no_hp_test:
  542.    cmp al,key_A    ; player hp = 10000
  543.    jne no_hp_up
  544.    mov [player_hp],10000
  545. no_hp_up:
  546.    cmp al,key_W    ; Run final screen
  547.    je  set_final_screen_window_from_call
  548. end if
  549.  
  550.    ; Keyboard array update, needs sub state
  551.    cmp al,01111111b
  552.    ja  key_released
  553.    mov byte [keymap+eax],'1'  ; If scan code of key down
  554.    jmp key_pressed
  555. key_released:
  556.    and al,01111111b
  557.    mov byte [keymap+eax],0    ; If scan code of key up
  558. key_pressed:
  559. this_is_hotkey:
  560.    ret
  561.  
  562. ;**********************
  563. ; Final screen process
  564. ;**********************
  565.  
  566. set_final_screen_window_from_call:
  567.    add esp,4    ; Remove call address from stack
  568. set_final_screen_window:
  569.    lea edx,[menu_keyboard]
  570.    mov ebx,1
  571.    lea ecx,[draw_final_screen_window]
  572.    jmp set_draw_proc
  573.  
  574. you_won_text: db 'YOU WON!',0
  575.  
  576. draw_final_screen_window:
  577.    draw_image 5,24,canvas
  578.    logo_font_size equ 5
  579.    logo_x = 5+(screen_w/2)-(6*logo_font_size*8/2)
  580.    logo_y = screen_h/16*5
  581.    draw_label logo_x,logo_y,you_won_text,cl_White+((logo_font_size-1) shl 24)
  582.    ;image_draw_label canvas,200,8,'YOU WON!',cl_White
  583.    draw_button 5,(screen_w/2)-40+5,300,80,14,'BACK TO MENU',cl_DarkRed,cl_Black
  584.  
  585.    clear_buffer canvas+8,canvas_end-canvas-8,7
  586.  
  587.    image_draw_acimage canvas,ship_img,(screen_w/2)-16,220,cl_Black
  588.    array_processing particles,draw_particles
  589.    array_processing particles,move_particles    ; move particles
  590.    array_processing particles,remove_outofscr_particles     ; del_outscreen_particles
  591.  
  592. try_to_make_firework:
  593.    inc [next_wave_timer]
  594.    cmp [next_wave_timer],30
  595.    jna no_firework
  596.    mov [next_wave_timer],0   ; reset firework timer before make firework
  597.    random screen_w-60,eax
  598.    mov ebx,eax
  599.    random screen_h-60,eax
  600.    mov edx,eax
  601.    mov ecx,8                 ; how much particles make in one fire explode
  602. next_star:
  603.    array_find particles,find_empty_object
  604.    jc  close_app
  605.    mov [edi],ebx        ; random x position
  606.    mov [edi+4],edx      ; random y position
  607.    mov [edi+8],dword 3  ; type of partice = 3. final screen particle
  608. rerand:
  609.    random 5,eax
  610.    sub eax,2
  611.    jz  rerand         ; eax = -2...2 exclude 0
  612.    mov [edi+12],eax   ; x velocity
  613. rerand2:
  614.    random 7,eax
  615.    sub eax,3
  616.    jz  rerand2        ; eax = -3...3 exclude 0
  617.    mov [edi+16],eax   ; y velocity
  618.    dec ecx
  619.    jnz next_star
  620. no_firework:
  621.    ret
  622.  
  623. ;***********************
  624. ;       Help menu
  625. ;***********************
  626.  
  627. set_help_window:
  628.    lea edx,[menu_keyboard]
  629.    mov ebx,-1
  630.    lea ecx,[draw_help_window]
  631.    jmp set_draw_proc
  632.  
  633. draw_help_window:
  634.    ; draw background and gray rectangle for label
  635.    ;draw_frect canvas size cl_Black
  636.    draw_frect 40,50,580,380,cl_Grey
  637.  
  638.    ; draw labels
  639.    mov ebp,4*7+3  ; Set value to labels counter
  640.    mov ebx,180*65536+90
  641.    mov edx,helptext
  642.    mov esi,50
  643.    mov ecx,cl_White+(10000000b shl 24)
  644. draw_next_string:
  645.    mov eax,4
  646.    mcall        ; Draw label
  647. @@:
  648.    mov al,[edx] ; Loop for find next zero
  649.    inc edx
  650.    cmp al,0
  651.    jne @b
  652.  
  653.    add ebx,10   ; Incrase y position of label
  654.    dec ebp      ; Decrase labels counter
  655.    jnz draw_next_string
  656.  
  657.    ; draw images of space objects
  658.    mov eax,90
  659.    mov ecx,7
  660. @@:
  661.    mov esi,[(img_offset-4)+ecx*4]
  662.    pushad
  663.    draw_image 90,eax,esi
  664.    popad
  665.    add eax,40
  666.    dec ecx
  667.    jnz @b
  668.  
  669.    draw_button 5,500,400,80,14,'< BACK',cl_DarkRed,cl_Black
  670.    ret
  671.  
  672. ; Offset to images showed in help screen in reverse sequence
  673. img_offset:
  674. dd box_img,asteroid_img,gwarship_img,bwarship_img
  675. dd plasma1_img,laser_img,ship_img
  676.  
  677. helptext:
  678.    db 'Phoenix - player ship',0
  679.    db 'Controls:',0
  680.    db 'Left or Right Arrows for move ship, P - button for pause',0
  681.    db 0
  682.    db 'Laser gun',0
  683.    db 'Recharge fast, speed fast. Projectile speed is medium',0
  684.    db 'Press Space button for shoot',0
  685.    db 0
  686.    db 'Plasma gun',0
  687.    db 'Recharge slow, reload fast. Projectile speed is fast',0
  688.    db 'Press Up button for shoot or Down button for make Nuke',0
  689.    db 0
  690.    db 'Blue warship',0
  691.    db 'Moving speed is fast',0
  692.    db 'Armed with plasma bombs',0
  693.    db 0
  694.    db 'Green warship',0
  695.    db 'Moving speed is medium',0
  696.    db 'Armed with laser gun',0
  697.    db 0
  698.    db 'Asteroid',0
  699.    db 'Is not destructable dangeros object!',0
  700.    db 'Collision with asteroid damage ship to much',0
  701.    db 0
  702.    db 'Repear Box',0
  703.    db 'Shield pack. Shield +5, Score +30',0
  704.    db 'Take on board for shield level up!',0
  705.    db 0,0,0
  706.    db 'Developed by Pavlushin Evgeni 2004',0
  707.  
  708. ; ****************************************
  709. ;          GLOBAL DRAW WINDOW
  710. ; ****************************************
  711.  
  712. draw_window:
  713.    window_begin_draw
  714.    mcall 0, <40, screen_w+9>, <40, screen_h+24+4>, 0x14000000,, wtitle
  715.    window_end_draw
  716.    ret
  717.  
  718. ; ****************************************
  719. ;           GAME PROCEDURE AREA
  720. ; ****************************************
  721.  
  722. ; Procedure for add ships to scene
  723. ; cl - number of ships which need to add 0..255
  724. ; ebp - offset to level string
  725. add_objects:
  726.    ; unpack values from ebx
  727.    xor eax,eax
  728.    mov al,ch
  729.    mov [shiptype],eax
  730.    mov al,bl
  731.    mov [yaccel],eax
  732.    mov al,bh
  733.    mov [ymoving],eax
  734.    shr ebx,16
  735.    mov al,bl
  736.    mov [xaccel],eax
  737.    mov al,bh
  738.    mov [xmoving],eax
  739. next_ship:
  740.    cmp cl,0
  741.    je  no_ships    ; if ships quantity = 0, exit from proc
  742.    push ecx
  743.    push ebp
  744.    ; find empty slot in space objects array
  745.    array_find objects,find_empty_object
  746.    jc  close_app
  747.    ; edi = offset to empty place in array
  748.    mov eax,[shiptype]
  749.    mov dword [edi+8],eax   ; store ship type
  750.    ; Randomize x position
  751.    random screen_w-32,eax
  752.    mov [edi],eax
  753.    ; Randomize y position
  754.    pop ebp
  755.    mov ax,[ebp+2]  ; get max range
  756.    cwde            ; extend ax to eax
  757.    random eax,eax
  758.    neg eax
  759.    mov [edi+4],eax
  760.    ; Randomize x moving
  761.    random [xmoving],eax
  762.    sub eax,[xaccel]
  763.    mov [edi+12],eax
  764.    ; Randomize y moving
  765.    random [ymoving],eax
  766.    add eax,[yaccel]
  767.    mov [edi+16],eax
  768.    pop ecx
  769.    dec cl
  770.    jnz next_ship
  771. no_ships:
  772.    ret
  773.  
  774. ; search empty slot in object array
  775. find_empty_object:
  776.    cmp [edi+8],dword 0  ; if object type == 0 then it empty
  777.    je  is_finded        ; empty object is finded set CF = 0
  778. ; find_next
  779.    stc     ; CF = 1
  780.    ret
  781. is_finded:
  782.    clc     ; CF = 0
  783.    ret
  784.  
  785. ; Try to draw particle from particle array
  786. draw_particles:
  787.    mov ecx,[edi+8]         ; ecx - type of particle
  788.    cmp ecx,0               ; if type == 0 then do not draw object
  789.    je  return
  790.    mov eax,laser_img
  791.    cmp ecx,Laser           ; this is laser particle
  792.    je  draw_space_object
  793.    mov eax,plasma2_img
  794.    cmp ecx,StaticPlasma    ; particle type for final screen animation
  795.    je  draw_space_object
  796.    random 3,ebx            ; if else this is Plasma particle
  797.    mov eax,plasma1_img
  798.    dec ebx
  799.    jz draw_space_object
  800.    mov eax,plasma2_img
  801.    dec ebx
  802.    jz draw_space_object
  803.    mov eax,plasma3_img
  804.    jmp draw_space_object
  805.  
  806. ; Draw space objects from array
  807. draw_objects:
  808.    mov ecx,[edi+8]         ; ecx = [edi+8] - type of ship
  809.    cmp ecx,0               ; if type of ship == 0 then not draw it
  810.    je  return
  811.    cmp ecx,(ot_end-object_type)/4+1
  812.    jae return              ; if type out of range ignore it
  813.    mov edx,[edi+4]         ; edx = [edi+4] - y position of ship
  814.    cmp edx,screen_h-40
  815.    jg  return
  816.    cmp edx,0               ; do not draw object if it y position is out of screen
  817.    jl  return
  818.    mov eax,[(object_type-4)+ecx*4]   ; -4 when types starts from 1 instead 0
  819. draw_space_object:
  820.    image_draw_acimage canvas,eax,dword [edi],dword [edi+4],cl_Black
  821. return:
  822.    ret
  823.  
  824. object_type: dd bwarship_img,gwarship_img,asteroid_img,box_img
  825. ot_end:
  826.  
  827. ; Update (move) particles (laser,plasma)
  828. move_particles:
  829.    xor eax,eax
  830.    cmp [edi+8],eax      ; Is object not empty ?
  831.    je this_is_empty_particle
  832. move_particle:
  833.    mov eax,[edi+12]
  834.    add [edi],eax        ; objectx + [edi+12]
  835.    mov eax,[edi+16]
  836.    add [edi+4],eax      ; objecty + [edi+16]
  837. this_is_empty_particle:
  838.    ret
  839.  
  840. ;  update (move) space objects (ships,asteroids,boxes)
  841. move_objects:
  842.    xor eax,eax
  843.    cmp [edi+8],eax
  844.    je  object_is_empty
  845.    ;call move_particle
  846.    mov eax,[edi+12]
  847.    add [edi],eax
  848.    mov eax,[edi+16]
  849.    add [edi+4],eax
  850.  
  851.    ; Do not allow object to go out of screen from right side
  852.    mov eax,screen_w-32     ; eax = right side of screen
  853.    cmp dword [edi],eax
  854.    jng right_side_ok
  855.    mov dword [edi],eax
  856.    neg dword [edi+12]
  857.    jmp left_side_ok
  858. right_side_ok:
  859.    ; Do not allow object to go out of screen from left side
  860.    xor eax,eax             ; eax = 0 - left side of screen
  861.    cmp dword [edi],eax
  862.    jnl left_side_ok
  863.    mov dword [edi],eax
  864.    neg dword [edi+12]
  865. left_side_ok:
  866.    ; If object out of screen remove it
  867.    cmp dword [edi+4],screen_h;-40
  868.    jng y_ok
  869.    mov dword [edi+8],0     ; Delete object
  870.    ret
  871. y_ok:
  872.    cmp dword [edi+8],GreenWarShip  ; Object is green enemy ship?
  873.    jne no_grs
  874.    mov eax,dword [edi+4]   ; eax = y position of enemy ship
  875.    ; alternative way is use random for shoot
  876.    cmp eax,100
  877.    jna no_grs
  878.    cmp eax,103
  879.    jna grs
  880.    cmp eax,200
  881.    jna no_grs
  882.    cmp eax,203
  883.    jna grs
  884.    cmp eax,300
  885.    jna no_grs
  886.    cmp eax,303
  887.    ja  no_grs
  888. grs:
  889.    ; invert y moving direction and make shoot
  890.    neg dword [edi+12]
  891.    mov [temp],edi
  892.    array_find particles,find_empty_object
  893.    jc  close_app
  894.    mov esi,[temp]      ; edi contains address to free element
  895.    mov [edi+8],dword 1
  896.    mov [edi+12],dword 0
  897.    mov [edi+16],dword 10
  898.    jmp set_particle_position
  899. no_grs:
  900.    cmp dword [edi+8],BlueWarShip  ; object is blue enemy ship ?
  901.    jne no_bls
  902.    mov ecx,dword [edi+4]
  903.    cmp ecx,50
  904.    jna no_bls
  905.    cmp ecx,64
  906.    jna bls
  907.    cmp ecx,100
  908.    jna no_bls
  909.    cmp ecx,114
  910.    jna bls
  911.    cmp ecx,150
  912.    jna no_bls
  913.    cmp ecx,164
  914.    ja  no_bls
  915. bls:
  916.    ; drop plasma mine
  917.    mov [temp],edi
  918.    array_find particles,find_empty_object
  919.    jc  close_app
  920.    mov esi,[temp]
  921.    mov [edi+8],dword 2
  922.    mov [edi+12],dword 0
  923.    mov [edi+16],dword 5
  924. set_particle_position:
  925.    mov eax,[esi]
  926.    mov [edi],eax       ; Particle x = Ship x
  927.    mov eax,[esi+4]
  928.    mov [edi+4],eax     ; Partcle y = Ship y
  929. no_bls:
  930. object_is_empty:
  931.    ret
  932.  
  933. ; Remove particles that have gone out off screen
  934. remove_outofscr_particles:
  935.    cmp dword [edi+4],40  ; test y position
  936.    jl  del
  937.    cmp dword [edi+4],screen_h-40
  938.    jg  del
  939.    cmp dword [edi],0     ; x test used for plasma shoots
  940.    jl  del
  941.    cmp dword [edi],screen_w-32
  942.    jg  del
  943.    ret        ; do not delete
  944. del:
  945.    xor eax,eax
  946.    mov [edi+8],eax ; [edi+8] = 0
  947. not_del:
  948.    ret
  949.  
  950. objects_and_particles_hit_handling:
  951.    xor eax,eax
  952.    cmp [esi+8],eax
  953.    je  no_hit
  954.    cmp [edi+8],eax    ; If object is empty skip crush test
  955.    je  no_hit
  956.    cmp [esi+16],eax
  957.    jg  no_hit
  958.  
  959.    mov eax,[esi]
  960.    shl eax,16
  961.    mov ax,word [esi+4]
  962.    mov ebx,32*65536+32
  963.    mov ecx,[edi]
  964.    shl ecx,16
  965.    mov cx,word [edi+4]
  966.    mov edx,32*65536+32
  967.  
  968.    game_collision_2d eax,ebx,ecx,edx
  969.    jnc no_hit
  970.  
  971.    cmp dword [edi+8],GreenWarShip
  972.    jne not_grship
  973.    inc [gships_destroyed]
  974.    add [score],30
  975.    jmp remove_object_and_particle
  976. not_grship:
  977.    cmp dword [edi+8],BlueWarShip
  978.    jne not_blship
  979.    inc [bships_destroyed]
  980.    add [score],20
  981.    jmp remove_object_and_particle
  982. not_blship:
  983.    cmp dword [edi+8],Asteroid
  984.    jne not_asteroid
  985.    cmp dword [edi+16],1 ; Asteroid have minimal speed?
  986.    je  remove_only_particle
  987.    dec dword [edi+16]   ; Decrase speed of asteroid
  988.    jmp remove_only_particle
  989. not_asteroid:
  990. remove_object_and_particle:  ; When hit to ship or box
  991.    mov [edi+8],dword 0
  992. remove_only_particle:        ; When hit to asteroid
  993.    mov [esi+8],dword 0
  994. no_hit:
  995.    ret
  996.  
  997. player_and_objects_collision_handling:
  998.    cmp [edi+8],dword 0
  999.    je  no_obj_cr
  1000.  
  1001.    mov eax,[shipx]
  1002.    shl eax,16
  1003.    mov ax,word [shipy]
  1004.    mov ebx,32*65536+32
  1005.    mov ecx,[edi]
  1006.    shl ecx,16
  1007.    mov cx,word [edi+4]
  1008.    mov edx,32*65536+32
  1009.  
  1010.    game_collision_2d eax,ebx,ecx,edx
  1011.    jnc no_obj_cr
  1012.    cmp dword [edi+8],Box  ; if box
  1013.    jne no_fbox
  1014.    add [player_hp],5
  1015.    add [score],50
  1016.    mov [edi+8],dword 0  ; delete object
  1017.    inc [boxes_taken]
  1018.    ret
  1019. no_fbox:
  1020.    sub [player_hp],16
  1021.    mov [edi+8],dword 0  ; delete object
  1022. no_obj_cr:
  1023.    ret
  1024.  
  1025. player_and_particles_collision_handling:
  1026.    xor eax,eax       ; use eax as zero
  1027.    cmp [edi+8],eax   ; empty object?
  1028.    je  no_gobj_cr
  1029.    cmp [edi+16],eax  ; is player ?
  1030.    jl  no_gobj_cr
  1031.  
  1032.    mov eax,[shipx]
  1033.    shl eax,16
  1034.    mov ax,word [shipy]
  1035.    mov ebx,32*65536+32
  1036.    mov ecx,[edi]
  1037.    shl ecx,16
  1038.    mov cx,word [edi+4]
  1039.    mov edx,32*65536+32
  1040.  
  1041.    game_collision_2d eax,ebx,ecx,edx
  1042.    jnc no_gobj_cr
  1043.    sub [player_hp],4
  1044.    mov [edi+8],dword 0  ; delete object
  1045. no_gobj_cr:
  1046.    ret
  1047.  
  1048. ;**************************
  1049. ; Player ship shoot procs
  1050. ;**************************
  1051.  
  1052. ; Try to make laser shoot
  1053. try_to_make_laser_shoot:
  1054.    cmp [laser_charge],dword 0
  1055.    jne no_laser_shoot     ; laser_shoots is heat, need time for recharge
  1056.    cmp [laser_shoots],dword 0
  1057.    je  no_laser_shoot     ; Don't shoot when so many laser particles on screen
  1058.    array_find particles,find_empty_object  ; edi = offset to emppty object
  1059.    jc  close_app          ; ?
  1060.    mov eax,[shipx]
  1061.    mov [edi],eax           ; 0  = x position of shoot
  1062.    mov eax,[shipy]
  1063.    mov [edi+4],eax         ; 4  = y position of shoot
  1064.    mov [edi+8],dword 1     ; 8  = 1 - laser type
  1065.    mov [edi+12],dword 0    ; 12 = 0   - x speed
  1066.    mov [edi+16],dword -12  ; 16 = -12 - y speed
  1067.    mov [laser_charge],dword 8  ; Reset shoot timer
  1068.    dec [laser_shoots]      ; Decrase number of laser projectiles
  1069. no_laser_shoot:
  1070.    ret
  1071.  
  1072. ; Try to make plasma shoot
  1073. try_to_make_plasma_shoot:
  1074.    cmp [plasma_charge],dword 256-16
  1075.    jae no_plasma_shoot
  1076.    cmp [plasma_shoots],0
  1077.    je  no_plasma_shoot
  1078.    array_find particles,find_empty_object
  1079.    ; edi = off to free element
  1080.    jc  close_app     ;?
  1081.    mov eax,[shipx]
  1082.    mov [edi],eax
  1083.    mov eax,[shipy]
  1084.    mov [edi+4],eax
  1085.    mov [edi+8],dword 2   ; 8 = 2 - plasma
  1086.    mov [edi+12],dword 0    ; 12 = 0   - x speed
  1087.    mov [edi+16],dword -8   ; 16 = -8 - y speed
  1088.    dec [plasma_shoots]     ; Decrase number of plasma projectiles
  1089.    add [plasma_charge],dword 8
  1090.    cmp [plasma_charge],dword 256
  1091.    jna no_plasma_shoot
  1092.    mov [plasma_charge],256
  1093. no_plasma_shoot:
  1094.    ret
  1095.  
  1096. ; Try to make plasma nuke
  1097. try_to_make_plasma_nuke:
  1098.    xor eax,eax     ; Use eax as zero
  1099.    cmp [plasma_charge],eax
  1100.    jne no_plasma_nuke
  1101.    cmp [plasma_shoots],eax
  1102.    je  no_plasma_nuke
  1103.    mov eax,[shipy]
  1104.    mov [temp3],eax
  1105.    mov [temp2],dword 5
  1106. loopx2:
  1107.    mov [temp],dword 10
  1108. loopx:
  1109.    array_find particles,find_empty_object ; edi = offset to empty element
  1110.    jc  close_app
  1111.    random 25,eax
  1112.    mov ebp,eax
  1113.    sub ebp,12
  1114.    add ebp,[shipx]
  1115.    mov [edi],ebp    ; [edi] = random(0..25)-12+shipx
  1116.    shr eax,3
  1117.    random eax,eax
  1118.    neg eax
  1119.    add eax,[temp3]
  1120.    mov [edi+4],eax
  1121.    mov [edi+8],dword 2  ; 8 = 2 - plasma
  1122.    random 5,eax
  1123.    sub eax,2
  1124.    mov [edi+12],eax
  1125.    random 7,eax
  1126.    sub eax,8
  1127.    mov [edi+16],eax
  1128.    dec [temp]
  1129.    jnz loopx
  1130.    sub [temp3],30     ; shipy - 30
  1131.    dec [temp2]
  1132.    jnz loopx2
  1133.    mov [plasma_charge],dword 256  ; Wait for cannon
  1134.    sub [plasma_shoots],50 ; -50 plasma bullets after nuke
  1135. no_plasma_nuke:
  1136.    ret
  1137.  
  1138. ; DATA AREA
  1139. IM_END:
  1140. wtitle db 'Phoenix for KOS', 0
  1141.  
  1142. score    dd 0    ; player score
  1143.  
  1144. ; Pause state, if != 0 then game on pause
  1145. pause_on dd 0
  1146.  
  1147. ; Frames countdown timer until start of next wave
  1148. ; If = 0 then activate to next wave
  1149. ; next_wave_timer
  1150. next_wave_timer dd 0
  1151.  
  1152. ;gif_file_area ~21500
  1153. ;gif_file_area2:
  1154. ;file 'phoenix.gif'
  1155. gif_file_area:
  1156. file 'objects.gif' ; Include gif file to code
  1157.  
  1158. IncludeUGlobals
  1159.  
  1160. ; Window drawing function delegate (pointer)
  1161. draw_proc rd 1
  1162. ; Keyboard processing function delegate (pointer)
  1163. keyboard_proc rd 1
  1164.  
  1165. ; Counter of objects on screen
  1166. objects_num rd 1
  1167.  
  1168. player_hp rd 1   ; Health points of player ship
  1169. shipx rd 1       ; Player ship x position
  1170. shipy rd 1       ; Player ship y position
  1171. ; guns
  1172. laser_shoots  rd 1 ; laser bullets quantity
  1173. plasma_shoots rd 1 ; plasma bullets quantity
  1174. ; Counters of player statistics
  1175. gships_destroyed rd 1 ; Number of green ships destroyed by player
  1176. bships_destroyed rd 1 ; Number of blue ships destroyed by player
  1177. boxes_taken rd 1      ; Number of repair boxes taken by player
  1178. ; Gun recharge counters
  1179. ; 0 = fully charged
  1180. ; 256 = fully uncharged
  1181. laser_charge  rd 1 ; Laser gun recharge counter
  1182. plasma_charge rd 1 ; Plasma gun recharge counter
  1183.  
  1184. ; Tempory varibles
  1185. temp  rd 1
  1186. temp2 rd 1
  1187. temp3 rd 1
  1188.  
  1189. event_mode rd 1   ; if -1 wait, 0 scan, n - n delay between events
  1190.  
  1191. ; Tempory varibles for add_objects proc
  1192. shiptype rd 1
  1193. xmoving  rd 1
  1194. ymoving  rd 1
  1195. xaccel   rd 1
  1196. yaccel   rd 1
  1197.  
  1198. ; Memory for contain not splitted image
  1199. objects_image: rb 8+288*32*3  ;8+256*64*3
  1200. ; Images sequence extracted from objects_image
  1201. ship_img:      rb 8+32*32*3   ; Player red space ship
  1202. laser_img:     rb 8+32*32*3   ; Double laser beams
  1203. bwarship_img:  rb 8+32*32*3   ; Blue enemy ship
  1204. gwarship_img:  rb 8+32*32*3   ; Green enemy ship
  1205. asteroid_img:  rb 8+32*32*3   ; Space asteroid
  1206. plasma1_img:   rb 8+32*32*3   ; Plasma big flash
  1207. plasma2_img:   rb 8+32*32*3   ; Plasma medium flash
  1208. plasma3_img:   rb 8+32*32*3   ; Plasma small flash
  1209. box_img:       rb 8+32*32*3   ; Repear kit box
  1210.  
  1211. ; array for storing state of keyboard keys
  1212. keymap:        rb 128
  1213.  
  1214. particles:
  1215. rd max_particles   ; dword = maximum number of particle objects
  1216. rd particle_size   ; dword = size of each particle object in bytes
  1217. rb max_particles*particle_size
  1218.  
  1219. objects:
  1220. rd max_objects     ; dword = maximum number of particles
  1221. rd object_size     ; dword = size of each object in bytes
  1222. rb max_objects*object_size
  1223.  
  1224. canvas:
  1225. rb 8+(screen_w*screen_h*3)
  1226. canvas_end:
  1227.  
  1228. ; application stack size
  1229. align 16
  1230. stack_max:
  1231.   rb 2048
  1232. I_END: