1,13 → 1,8 |
; |
; Phenix Dynamic Game Created by Pavlushin Evgeni for ASCL |
; Phoenix Game. Based on ASCL Library |
; |
; 100% Full relase! |
; |
; www.waptap@mail.ru |
; |
|
|
;****************************************************************************** |
;********************************************************************** |
use32 |
org 0x0 |
db 'MENUET01' ; 8 byte id |
15,1336 → 10,1223 |
dd START ; start of code |
dd IM_END ; size of image |
dd I_END ; memory for app |
dd I_END ; esp |
dd I_END ; esp stack position |
dd 0x0 , 0x0 ; I_Param , I_Icon |
;********************************************************************** |
|
;****************************************************************************** |
include 'lang.inc' ; for SVN 'lang.inc' |
include '../../../macros.inc' ; for SVN '..\..\..\macros.inc;' |
include 'ascl.inc' ; main |
include 'ascgl.inc' ; graphics |
include 'ascpoal.inc' ; processing object array |
include 'ascgml.inc' ; game library for collision detection |
|
; debug flags |
keyboard_debug=0 ; Set to 1 to view all keyboard keys state in game |
light_space=0 ; May used for check canvas position in window |
debug_scenario=0 ; May used for fast test of gameplay |
stack_leak_debug=0 ; Show stack size on screen |
debug_mode=1 ; Support keys: |
; A - set player hp = 10000. Make player ship undestructible |
; E - player hp / 2 |
; W - view final screen after game begin |
|
include 'lang.inc' |
include '../../../macros.inc' |
include 'ascl.inc' |
include 'ascgl.inc' |
include 'ascml.inc' |
screen_w equ 640 |
screen_h equ 440 |
;screen_w equ 1014 |
;screen_h equ 739 |
|
; Define special colors |
cl_DarkRed equ 0x990000 |
cl_Orange equ 0xbbbb00 |
|
showmas: |
cmp [edi+8],dword 0 |
je noshow |
cmp [edi+8],dword 1 |
jne no_gun |
mov eax,shoot |
jmp outp |
no_gun: |
push edi |
random 3,ebx |
pop edi |
cmp ebx,0 |
jne no_star |
mov eax,star |
jmp outp |
no_star: |
cmp ebx,1 |
jne no_star2 |
mov eax,star2 |
jmp outp |
no_star2: |
mov eax,star3 |
outp: |
aimgtoimg eax,dword [edi],dword [edi+4],canvas,0x0 |
noshow: |
ret |
; Define objects type id |
EmptyObject equ 0 |
; This numbers not possible for modify because draw_objects: |
BlueWarShip equ 1 |
GreenWarShip equ 2 |
Asteroid equ 3 |
Box equ 4 |
|
showobjmas: |
cmp [edi+8],dword 0 |
je noshow1 |
cmp [edi+4],dword 380 |
jg noshow1 |
cmp [edi+4],dword 0 |
jl noshow1 |
cmp [edi+8],dword 1 |
jne no_warship1 |
mov eax,warship1 |
jmp outws |
no_warship1: |
cmp [edi+8],dword 2 |
jne no_warship2 |
mov eax,warship2 |
jmp outws |
no_warship2: |
cmp [edi+8],dword 3 |
jne no_meteor |
mov eax,meteor |
jmp outws |
no_meteor: |
cmp [edi+8],dword 4 |
jne no_box |
mov eax,box |
jmp outws |
no_box: |
outws: |
aimgtoimg eax,dword [edi],dword [edi+4],canvas,0x0 |
noshow1: |
ret |
Laser equ 1 |
Plasma equ 2 |
StaticPlasma equ 3 |
|
;************************************************************** |
; Start of programm |
;************************************************************** |
|
moveobjmas: |
cmp [edi+8],dword 0 |
je no_ws |
mov eax,[edi+12] |
add [edi],eax |
mov eax,[edi+16] |
add [edi+4],eax |
START: ; start of execution |
|
cmp dword [edi],600 |
jng xok1 |
sub dword [edi],20 |
neg dword [edi+12] |
jmp xok2 |
xok1: |
cmp dword [edi],0 |
jnl xok2 |
add dword [edi],20 |
neg dword [edi+12] |
xok2: |
cmp dword [edi+4],400 |
jng yok |
mov dword [edi+8],0 |
ret |
yok: |
cmp dword [edi+8],2 ;green ship |
jne no_grs |
cmp dword [edi+4],100 |
jna no_grs |
cmp dword [edi+4],103 |
jna grs |
cmp dword [edi+4],200 |
jna no_grs |
cmp dword [edi+4],203 |
jna grs |
cmp dword [edi+4],300 |
jna no_grs |
cmp dword [edi+4],303 |
ja no_grs |
grs: |
neg dword [edi+12] |
mov [temp],edi |
findmas massive,findzero |
;in edi off to free element |
jc close_app |
mov esi,edi |
mov edi,[temp] |
mov eax,[edi] |
mov [esi],eax |
mov eax,[edi+4] |
mov [esi+4],eax |
mov [esi+8],dword 1 |
mov [esi+12],dword 0 |
mov [esi+16],dword 10 |
no_grs: |
max_particles = 400 |
particle_size = 20 |
|
cmp dword [edi+8],1 ;blue ship |
jne no_bls |
cmp dword [edi+4],50 |
jna no_bls |
cmp dword [edi+4],64 |
jna bls |
cmp dword [edi+4],100 |
jna no_bls |
cmp dword [edi+4],114 |
jna bls |
cmp dword [edi+4],150 |
jna no_bls |
cmp dword [edi+4],164 |
ja no_bls |
bls: |
mov [temp],edi |
findmas massive,findzero |
jc close_app |
mov esi,edi |
mov edi,[temp] |
mov eax,[edi] |
mov [esi],eax |
mov eax,[edi+4] |
mov [esi+4],eax |
mov [esi+8],dword 2 |
mov [esi+12],dword 0 |
mov [esi+16],dword 5 |
no_bls: |
mov [particles],dword max_particles |
mov [particles+4],dword particle_size |
|
no_ws: |
ret |
max_objects = 100 |
object_size = 20 |
|
mov [objects],dword max_objects |
mov [objects+4],dword object_size |
|
delfarshoot: |
cmp [edi+4],dword 40 |
jb del |
cmp [edi+4],dword 400 |
ja del |
cmp [edi],dword 40 |
jb del |
cmp [edi],dword 600 |
ja del |
jmp nodel |
del: |
mov [edi+8],dword 0 |
nodel: |
ret |
keyboard_set_input_mode 1 ; 0 - ASCII; 1 - scancodes; |
|
;giftoimg gif_file_area2,canvas |
giftoimg gif_file_area,objects_image |
|
movemas: |
cmp [edi+8],dword 0 |
jne no_freeel |
ret |
no_freeel: |
mov eax,[edi+12] |
add [edi],eax |
mov eax,[edi+16] |
add [edi+4],eax |
ret |
; load sprites |
mov cl,9 ; cl - counter |
xor esi,esi ; esi = 0 |
lea edi,[ship_img] ; address of first sprite |
load_sprite: |
pushad |
getimg objects_image,esi,0,32,32,edi |
popad |
add edi,8+32*32*3 ; incrase offest of image data |
add esi,32 ; incrase x position |
dec cl |
jnz load_sprite |
|
set_main_menu: |
mov ebx,-1 ; at start event_mode = -1 |
lea ecx,[draw_main_window] |
lea edx,[menu_keyboard] |
set_draw_proc: |
; assembler extract command ; for use only bl |
mov [event_mode],ebx |
mov [draw_proc],ecx |
mov [keyboard_proc],edx |
; at first draw window |
main_menu: |
redraw_event: ; redraw event appears if user move, show/hide window |
call draw_window |
no_event: |
call [draw_proc] ; no event no requre draw_window for no flickering |
if stack_leak_debug = 1 |
; stack memory leak debug |
lea ebp,[I_END] |
sub ebp,esp |
outcount ebp,10,30,cl_Green,5*65536 |
end if |
menu_loop: |
;wait_event redraw_event,keyboard_event,button_event |
mov eax,10 ; wait event |
mov ebx,[event_mode] |
cmp ebx,-1 ; ebx delay for mcall 23 |
je wait_ev |
mov eax,23 ; time event |
wait_ev: |
mcall |
dec eax |
js no_event |
jz redraw_event |
dec eax |
jz keyboard_event |
dec eax |
jz button_event |
jmp menu_loop ; if unknown event, skip it |
|
keyboard_event: ; keyboard event if user press button |
call [keyboard_proc] |
jmp menu_loop |
button_event: |
window_get_button |
cmp ah,1 ; if button id=1 (Red X of window) then close app |
je close_app |
cmp ah,2 ; if button id=2 then close app |
je close_app |
cmp ah,3 ; if button id=3 then start game |
je start_game |
cmp ah,4 ; if button id=3 then show help menu |
je set_help_window ; jmp with redraw window |
cmp ah,5 ; if button id=5 then back to main menu |
je set_main_menu ; jmp with redraw window |
cmp ah,6 |
je next_level ; run next level |
cmp ah,7 |
je restart_lev ; restart level from gameover |
cmp ah,9 |
je set_game_window ; back to game from menu |
jmp menu_loop |
|
endshowmas: |
cmp [edi+8],dword 0 |
je noshowem |
mov eax,star2 |
aimgtoimg eax,dword [edi],dword [edi+4],canvas,0x0 |
noshowem: |
ret |
close_app: |
mov eax,-1 ; close this program |
mcall |
|
|
|
endmovemas: |
cmp [edi+8],dword 0 |
jne no_fr |
menu_keyboard: |
; nothing do |
window_get_key |
ret |
no_fr: |
mov eax,[edi+12] |
add [edi],eax |
mov eax,[edi+16] |
add [edi+4],eax |
ret |
|
;*********************** |
; Main screen menu |
;*********************** |
|
findzero: |
cmp [edi+8],dword 0 |
je iz_zero |
xor eax,eax |
draw_main_window: |
draw_label 160,160,'Phoenix',cl_Red+font_size_x8 |
draw_button 3,300,320,60,14,'START',cl_DarkRed,cl_Yellow |
draw_button 4,300,340,60,14,'HELP',cl_DarkRed,cl_Yellow |
draw_button 2,300,360,60,14,'EXIT',cl_DarkRed,cl_Yellow |
ret |
iz_zero: |
mov eax,1 |
ret |
|
compobr: |
cmp [esi+8],dword 0 |
je no_crsh |
cmp [edi+8],dword 0 |
je no_crsh |
cmp [esi+16],dword 0 |
jg no_crsh |
;********************** |
; End level process |
;********************** |
|
mov eax,[esi] |
mov [temp],eax |
mov eax,[esi+4] |
mov [temp2],eax |
mov eax,[edi] |
mov [temp3],eax |
mov eax,[edi+4] |
mov [temp4],eax |
set_end_level_window_from_call: |
add esp,4 ; remove call address from stack |
set_end_level_window: |
lea edx,[menu_keyboard] |
mov ebx,-1 |
lea ecx,[draw_end_level_window] |
jmp set_draw_proc |
|
pushad |
collimg imgsize,[temp],[temp2],imgsize,[temp3],[temp4],[otv] |
popad |
cmp [otv],dword 0 |
je no_crsh |
draw_end_level_window: |
draw_frect 170,130,300,190,cl_Grey |
draw_label 280,150,'LEVEL COMPLETE',cl_Black |
draw_button 2,180,300,80,14,'EXIT',cl_DarkRed,cl_Black |
draw_button 5,280,300,80,14,'<MENU>',cl_DarkRed,cl_Black |
draw_button 6,380,300,80,14,'NEXT >',cl_DarkRed,cl_Black |
|
cmp [edi+8],dword 2 |
jne no_grship |
inc [gship] |
add [score],30 |
jmp setzero |
no_grship: |
cmp [edi+8],dword 1 |
jne no_blship |
inc [bship] |
add [score],20 |
jmp setzero |
no_blship: |
cmp [edi+8],dword 3 |
jne no_metr |
dec dword [edi+16] |
cmp dword [edi+16],0 |
jne mok |
mov dword [edi+16],1 |
mok: |
mov [esi+8],dword 0 |
ret |
no_metr: |
draw_image 180,170,bwarship_img |
draw_number [bships_destroyed],240,185,cl_Blue,3*65536 |
|
setzero: |
mov [esi+8],dword 0 |
mov [edi+8],dword 0 |
no_crsh: |
ret |
draw_image 180,210,gwarship_img |
draw_number [gships_destroyed],240,225,cl_Green,3*65536 |
|
shipobjtest: |
cmp [edi+8],dword 0 |
je no_obj |
mov eax,[edi] |
mov [temp3],eax |
mov eax,[edi+4] |
mov [temp4],eax |
pushad |
collimg imgsize,[shipx],[shipy],imgsize,[temp3],[temp4],[otv] |
popad |
cmp [otv],dword 0 |
je no_obj |
cmp [edi+8],dword 4 ;if box |
jne no_fbox |
add [energy],5 |
add [score],50 |
mov [edi+8],dword 0 |
inc [boxget] |
draw_image 180,250,box_img |
draw_number [boxes_taken],240,265,cl_Orange,3*65536 |
ret |
no_fbox: |
sub [energy],16 |
mov [edi+8],dword 0 |
no_obj: |
ret |
|
shipguntest: |
cmp [edi+8],dword 0 |
je no_gobj |
cmp [edi+16],dword 0 |
jl no_gobj |
mov eax,[edi] |
mov [temp3],eax |
mov eax,[edi+4] |
mov [temp4],eax |
pushad |
collimg imgsize,[shipx],[shipy],imgsize,[temp3],[temp4],[otv] |
popad |
cmp [otv],dword 0 |
je no_gobj |
sub [energy],4 |
mov [edi+8],dword 0 |
no_gobj: |
ret |
;********************** |
; Game Over process |
;********************** |
|
restart_lev: |
mov [next_wave_timer],0 ; Reset new wave timer |
prevpart: |
call get_wave_info_offset |
xor eax,eax |
mov ax,[ebp] |
dec eax ; If eax = 0 then start of level finded |
jz reset_all_varibles_and_restart_level |
dec [level_wave] |
jmp prevpart |
|
START: ; start of execution |
set_game_over_window_from_call: |
add esp,4 |
set_game_over_window: |
lea edx,[menu_keyboard] |
mov ebx,-1 |
lea ecx,[draw_game_over_window] |
jmp set_draw_proc |
|
massize = 400 |
elemsize = 20 |
|
mov [massive],dword massize |
mov [massive+4],dword elemsize |
|
omassize = 100 |
oelemsize = 20 |
|
mov [objmas],dword omassize |
mov [objmas+4],dword oelemsize |
|
|
mov eax,66 |
mov ebx,1 |
mov ecx,1 |
mcall |
|
mov eax,26 |
mov ebx,2 |
mov ecx,1 |
mov edx,keymap |
mcall |
|
startgame: |
giftoimg gif_file_area2,canvas |
giftoimg gif_file_area,img_area |
|
getimg img_area,0,0,32,32,ship |
getimg img_area,32,0,32,32,shoot |
getimg img_area,64,0,32,32,warship1 |
getimg img_area,96,0,32,32,warship2 |
getimg img_area,128,0,32,32,meteor |
getimg img_area,160,0,32,32,star |
getimg img_area,192,0,32,32,star2 |
getimg img_area,224,0,32,32,star3 |
getimg img_area,0,32,32,32,box |
|
|
|
main_menu: |
call draw_logowindow |
|
stillm: |
wtevent redm,keym,buttonm |
jmp stillm |
redm: |
call draw_logowindow |
jmp stillm |
keym: |
mov eax,2 |
mcall |
jmp stillm |
buttonm: |
mov eax,17 ; get id |
mcall |
cmp ah,1 ; button id=1 ? |
je close_app |
cmp ah,2 ; button id=1 ? |
je start_game |
cmp ah,3 ; button id=1 ? |
je help |
cmp ah,4 ; button id=1 ? |
je close_app |
jmp stillm |
|
draw_logowindow: |
call draw_window |
mcall 9,proc_info,-1 |
test [proc_info+process_information.wnd_state], 0x04 |
jz @f |
draw_game_over_window: |
draw_frect 170,160,300,120,cl_Grey |
draw_label 292,200,'GAME OVER',cl_Black |
draw_button 2,180,260,80,14,'EXIT',cl_DarkRed,cl_Black |
draw_button 5,280,260,80,14,'MENU',cl_DarkRed,cl_Black |
draw_button 7,380,260,80,14,'RESTART',cl_DarkRed,cl_Black |
ret |
@@: |
setimg 5,21,canvas |
drawlbut 300,300,60,14,'START',2,0x990000,cl_Black |
drawlbut 300,320,60,14,'HELP',3,0x990000,cl_Black |
drawlbut 300,340,60,14,'EXIT',4,0x990000,cl_Black |
ret |
|
;*********************** |
; Draw help menu |
; Main game loop |
;*********************** |
|
help: |
call draw_helpwindow |
next_level: |
mov [next_wave_timer],0 ; Reset next wave timer |
inc [level_wave] ; Next wave |
start_game: |
; Set canvas size before logo is showed |
image_set_size canvas,screen_w,screen_h |
|
stillh: |
wtevent redh,keyh,buttonh |
jmp stillh |
redh: |
call draw_helpwindow |
jmp stillh |
keyh: |
mov eax,2 |
mcall |
jmp stillh |
buttonh: |
mov eax,17 ; get id |
mcall |
cmp ah,1 ; button id=1 ? |
je close_app |
cmp ah,2 ; button id=1 ? |
je start_game |
cmp ah,3 ; button id=1 ? |
je help |
cmp ah,4 ; button id=1 ? |
je close_app |
cmp ah,5 ; button id=1 ? |
je main_menu |
jmp stillh |
; Clear all, and prepeare varibles before start |
reset_all_varibles_and_restart_level: |
|
draw_helpwindow: |
call draw_window |
mcall 9,proc_info,-1 |
test [proc_info+process_information.wnd_state], 0x04 |
jnz stillh |
setimg 5,21,canvas |
; Clear objects arrays |
mov eax,0 |
cld |
mov edi,particles+8 |
mov ecx,max_particles*particle_size/4 |
rep stosd |
mov edi,objects+8 |
mov ecx,max_objects*object_size/4 |
rep stosd |
|
drawfbox 40,50,580,380,cl_Grey |
; Reset keyboard state array |
clear_buffer keymap, 128, 0 |
|
mov ebp,4*7 |
mov ebx,180*65536+90 |
mov edx,helptext |
mov esi,50 |
mov ecx,cl_White |
dec ebp |
looht: |
mov eax,4 |
mcall |
add edx,esi |
add ebx,10 |
dec ebp |
jnz looht |
; Reset player ship state |
mov [player_hp],100 |
mov [shipx],screen_w/2-16 ; Player ship x start position |
mov [shipy],screen_h-40 ; Player ship y start position |
mov [laser_shoots],1000 ; Laser projectiles at start |
mov [plasma_shoots],500 ; Plasma projectiles at start |
|
setimg 90,90,ship |
setimg 90,130,shoot |
setimg 90,170,star |
setimg 90,210,warship1 |
setimg 90,250,warship2 |
setimg 90,290,meteor |
setimg 90,330,box |
; Reset counters and gun charge values |
xor eax,eax |
mov [boxes_taken],eax |
mov [gships_destroyed],eax |
mov [bships_destroyed],eax |
mov [laser_charge],eax |
mov [plasma_charge],eax |
|
drawlbut 500,400,80,14,'<<BACK',5,0x990000,cl_Black |
set_game_window: |
lea edx,[ingame_keyboard] |
lea ecx,[draw_game_window] |
mov ebx,2 ; time_event ebx = 2 ms |
jmp set_draw_proc |
|
jmp stillh |
draw_game_window: |
draw_image 5,24,canvas |
|
helptext: |
db 'Phenix ' |
db 'Controls: Num1 move left, Num3 move right ' |
db ' P-pause (use for screen shooting) ' |
db ' ' |
xor eax,eax ; Use eax as zero for compare |
cmp [pause_on],eax ; If pause = 0 nothing do |
je no_pause |
ret |
no_pause: |
|
db 'Lazer cannon ' |
db 'Press Num5 for shoot ' |
db 'Core fast, speed fast, reload slow ' |
db ' ' |
cmp [player_hp],eax ; If player_hp < 0 game over |
jl set_game_over_window_from_call |
|
db 'Plazma cannon ' |
db 'Press Num2 for Plazma Nuke and Num8 for shoot ' |
db 'Core slow, speed medium, reload fast ' |
db ' ' |
cmp [laser_charge],eax |
je no_dec_laser_charge |
dec dword [laser_charge] ; If laser_charge > 0 decrase it |
no_dec_laser_charge: |
cmp [plasma_charge],eax |
je no_dec_plasma_charge |
dec dword [plasma_charge] ; If plasma_charge > 0 decrase it |
no_dec_plasma_charge: |
|
db 'Blue warship ' |
db 'Speed fast ' |
db 'Attack method: plazma bomb ' |
db ' ' |
; new wave test |
inc dword [next_wave_timer] |
call get_wave_info_offset |
mov ax,[ebp] ; [ebp] = time to activate string |
cwde ; extend ax to eax |
cmp [next_wave_timer],eax |
jne no_next_wave |
|
db 'Green warship ' |
db 'Speed slow ' |
db 'Attack method: laser shoot ' |
db ' ' |
add_new_wave_of_objects: |
mov cl,[ebp+4+0] ; cl = count of ships |
mov ch,GreenWarShip ; ch = type of object |
mov ebx,0x09040302 ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel] |
call add_objects ; add objects |
|
db 'Meteor ' |
db 'Dangeros object! ' |
db 'SuperSheld ' |
db ' ' |
mov cl,[ebp+4+1] ; cl = count of ships |
mov ch,BlueWarShip ; ch = type of object |
mov ebx,0x03010306 ; ebx = random ranges : x = -1..1 y = -6..-4 |
call add_objects ; add objects |
|
db 'Fly Box ' |
db 'Sheld pack, sheld +5, score +30 ' |
db 'Get for sheld level up! ' |
db ' ' |
mov cl,[ebp+4+2] ; cl = count of asteroids |
mov ch,Asteroid ; ch = type of object |
mov ebx,0x05020502 ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel] |
call add_objects ; add objects |
|
start_game: |
mov cl,[ebp+4+3] ; cl = count of boxes |
mov ch,Box ; ch = type of object |
mov ebx,0x05020401 ; ebx = [xmoving]:[xaccel]:[ymoving]:[yaccel] |
call add_objects ; add objects |
|
; jmp end_gm |
mov [next_wave_timer],0 ; Reset next wave timer |
inc [level_wave] ; Next wave |
no_next_wave: |
|
mov [canvas],dword 640 |
mov [canvas+4],dword 440 |
; Calculate all active objects on screen |
xor eax,eax ; Use eax as zero |
mov [objects_num],eax |
array_processing objects,endtest ; ar_proc not modify eax, ebx |
xor eax,eax ; Use eax as zero |
cmp [objects_num],eax ; If [objects_num] != 0, level is not complete |
jnz level_not_complete |
|
call draw_window |
call get_wave_info_offset |
mov ax,[ebp+2] ; ax = maxyrange |
cwde ; extend ax to eax |
xor ebx,ebx ; Use ebx as zero for compare |
cmp eax,ebx ; If [ebp+2] of level = 0, this is end of level |
je set_end_level_window_from_call ; Show player score |
dec ebx ; Use ebx as -1 for compare |
cmp eax,ebx |
je set_final_screen_window_from_call ; Show final animation |
level_not_complete: |
|
;Main loop wait for event with 10msec |
still: |
; scevent red,key,button ;for full speed |
no_end_lev: |
|
timeevent 1,no_event,red,key,button |
no_event: |
mcall 9,proc_info,-1 |
test [proc_info+process_information.wnd_state], 0x04 |
jnz still |
setimg 5,21,canvas |
; Key state processing |
cmp byte [keymap+key_Right],0 |
je no_key_right |
add dword [shipx],6 |
no_key_right: |
cmp byte [keymap+key_Left],0 |
je no_key_left |
sub dword [shipx],6 |
no_key_left: |
cmp byte [keymap+key_Space],0 |
je no_key_lshoot |
call try_to_make_laser_shoot |
;call try_to_make_plasma_shoot |
no_key_lshoot: |
cmp byte [keymap+key_Up],0 |
je no_key_pshoot |
;call try_to_make_plasma_nuke |
call try_to_make_plasma_shoot |
no_key_pshoot: |
cmp byte [keymap+key_Down],0 |
je no_key_pnuke |
call try_to_make_plasma_nuke |
;call try_to_make_laser_shoot |
no_key_pnuke: |
|
cmp [pause_on],0 |
jne still |
; Ship position correction (clamp macro) |
cmp [shipx],5 |
jnl @f |
mov [shipx],5 |
@@: |
cmp [shipx],screen_w-32-5 |
jng @f |
mov [shipx],screen_w-32-5 |
@@: |
|
cmp [energy],0 |
jl game_over |
mov al,7 |
if light_space = 1 |
mov al,255 |
end if |
clear_buffer canvas+8,canvas_end-canvas-8,al |
|
cmp [ctime],dword 0 |
je no_dct |
dec dword [ctime] |
no_dct: |
compmas objects,particles,objects_and_particles_hit_handling |
; move objects and particles |
array_processing objects,move_objects |
array_processing particles,move_particles |
; remove particles out of screen |
array_processing particles,remove_outofscr_particles |
; objects and particles collision test |
array_processing objects,player_and_objects_collision_handling |
array_processing particles,player_and_particles_collision_handling |
; draw objects and particles |
array_processing objects,draw_objects |
array_processing particles,draw_particles |
; draw player ship |
image_draw_acimage canvas,ship_img,[shipx],[shipy],cl_Black |
|
cmp [xtime],dword 0 |
je no_dxt |
dec dword [xtime] |
no_dxt: |
; Draw info indicators |
draw_frect 150,5,64,5,cl_Black |
mov eax,[plasma_charge] |
sub eax,256 |
neg eax |
shr eax,2 |
draw_frect 150,5,eax,5,cl_Cyan |
|
draw_frect 150,12,64,5,cl_Black |
mov eax,[laser_charge] |
sub eax,8 |
neg eax |
shl eax,3 |
draw_frect 150,12,eax,5,cl_Yellow |
|
; |
; Add to level new ships |
; |
inc dword [pathtime] |
mov ebp,[levelpart] |
shl ebp,5 |
add ebp,levels |
mov eax,[ebp] |
cmp [pathtime],eax ;500 |
jne no_nextloc |
draw_frect 220,2,6*5+2 ,9,cl_Grey |
draw_number [plasma_shoots],221,3,cl_Cyan,5*65536 |
draw_frect 220,11,6*5+2 ,9,cl_Grey |
draw_number [laser_shoots],221,12,cl_Yellow,5*65536 |
|
randobjmasx: |
mov ebp,[levelpart] |
shl ebp,5 |
add ebp,levels |
draw_frect 280,6,6*5+2 ,9,cl_Grey |
draw_number [gships_destroyed],281,7,cl_Green,5*65536 |
draw_frect 320,6,6*5+2 ,9,cl_Grey |
draw_number [bships_destroyed],321,7,cl_Blue,5*65536 |
draw_frect 360,6,6*5+2 ,9,cl_Grey |
draw_number [boxes_taken],361,7,0xffaa00,5*65536 |
|
mov ecx,[ebp+8] |
mov [shiptype],2 |
mov [xmoving],9 |
mov [xaccel],4 |
mov [ymoving],3 |
mov [yaccel],2 |
call add_ships |
; number of objects in scene |
draw_frect 400,2,6*5+2 ,9,cl_Grey |
draw_number [objects_num],401,2,cl_Lime,5*65536 |
|
mov ecx,[ebp+12] |
mov [shiptype],1 |
mov [xmoving],3 |
mov [xaccel],1 |
mov [ymoving],3 |
mov [yaccel],6 |
call add_ships |
draw_frect 400,11,6*5+2 ,9,cl_Grey |
draw_number [player_hp],401,12,cl_Red,5*65536 |
|
mov ecx,[ebp+16] |
mov [shiptype],3 |
mov [xmoving],5 |
mov [xaccel],2 |
mov [ymoving],5 |
mov [yaccel],2 |
call add_ships |
draw_frect 450,11,6*5+2 ,9,cl_Grey |
draw_number [score],451,12,cl_Yellow,5*65536 ;+hide_zeros |
|
mov ecx,[ebp+20] |
mov [shiptype],4 |
mov [xmoving],4 |
mov [xaccel],1 |
mov [ymoving],4 |
mov [yaccel],1 |
call add_ships |
; print keyboard keys state as string for debug |
if keyboard_debug = 1 |
mov ebx,10*65536+40 |
mov edx,keymap |
mov esi,128 |
mov ecx,cl_White |
mov eax,4 |
mcall |
end if |
ret |
|
jmp newlocend |
; Proc for calculate active objects on screen |
; eax - empty object type = 0 |
endtest: |
xor eax,eax |
cmp dword [edi+8],eax ; object is empty ? |
je is_free |
inc [objects_num] |
is_free: |
ret |
|
shiptype dd 0 |
xmoving dd 0 |
ymoving dd 0 |
xaccel dd 0 |
yaccel dd 0 |
|
add_ships: |
looship: |
cmp ecx,0 |
je no_ships |
push ecx |
findmas objmas,findzero |
;in edi off to free element |
jc close_app |
mov ebp,[shiptype] |
mov dword [edi+8],ebp ;2 ;green ship |
; random x |
push edi |
random 600,eax |
pop edi |
mov [edi],eax |
; random y |
push edi |
mov ebp,[levelpart] |
shl ebp,5 |
add ebp,levels |
mov esi,[ebp+4] ;get max range |
random esi,eax |
neg eax |
pop edi |
mov [edi+4],eax |
; x moving |
push edi ;planers |
random [xmoving],eax |
sub eax,[xaccel];4 |
pop edi |
mov [edi+12],eax |
; y moving |
push edi |
random [ymoving],eax ;slow |
add eax,[yaccel] ;2 |
pop edi |
mov [edi+16],eax |
pop ecx |
dec ecx |
jnz looship |
no_ships: |
; Proc for get offest to current level wave information |
get_wave_info_offset: |
mov ebp,[level_wave] |
shl ebp,3 ; ebp = ebp*8; 8 - lenght of one string in levels array |
add ebp,levels ; ebp = offset to string in levels array |
ret |
|
; time_bwns - time before next wave start |
; yrmax - y random position maximum value |
macro objects_wave time_bnws, yrmax, gships, bships, asteroids, boxes{ |
dw time_bnws, yrmax |
db gships, bships, asteroids, boxes |
} |
|
levelpart dd 0 |
level_wave dd 0 |
; this array may optimized |
levels: |
; for game not ended at start, each level must have objects set at start (1) |
; test pattern |
if debug_scenario = 1 |
; two levels for debug game |
objects_wave 1, 10, 1, 2, 4, 8 ; objset at start |
objects_wave 0, 0, 0, 0, 0, 0 |
objects_wave 1, 10, 3, 3, 3, 3 ; objset at start |
objects_wave 0, -1, 0, 0, 0, 0 |
else |
;level1 |
dd 1,800,0,0,5,8,0,0 ;one at start |
dd 500,2000,4,20,30,0,0,0 |
dd 500,2000,4,20,0,8,0,0 |
dd 500,2000,10,0,0,4,0,0 |
dd 500,4000,0,30,0,0,0,0 |
dd 400,400,0,0,10,0,0,0 |
dd 400,400,0,0,10,0,0,0 |
dd 0,0,0,0,0,0,0,0 ;end of level |
objects_wave 1, 4000, 3, 10, 10, 0 ; objset at start |
objects_wave 800, 2000, 5, 3, 5, 3 |
objects_wave 400, 2000, 3, 7, 5, 3 |
objects_wave 400, 800, 3, 5, 3, 0 |
objects_wave 0, 0, 0, 0, 0, 0 ; end of level |
;level2 |
dd 1,16000,0,30,0,0,0,0 ;one at start |
dd 200,8000,0,20,0,0,0,0 |
dd 200,2000,0,10,0,8,0,0 |
dd 200,4000,0,10,0,0,0,0 |
dd 0,0,0,0,0,0,0,0 ;end of level |
objects_wave 1, 4000, 10, 40, 0, 8 ; objset at start |
objects_wave 400, 4000, 10, 10, 20, 6 |
objects_wave 400, 2000, 0, 20, 10, 2 |
objects_wave 400, 400, 10, 10, 20, 0 |
objects_wave 0, 0, 0, 0, 0, 0 ; end of game |
;level3 |
dd 1,4000,0,20,30,8,0,0 ;one at start |
dd 400,4000,10,10,20,6,0,0 |
dd 400,4000,0,20,10,2,0,0 |
dd 400,4000,10,10,20,0,0,0 |
dd 0,-1,0,0,0,0,0,0 ;end of game |
objects_wave 1, 800, 0, 0, 5, 5 ; objset at start |
objects_wave 500, 2000, 4, 20, 30, 0 |
objects_wave 500, 2000, 4, 20, 0, 8 |
objects_wave 500, 2000, 10, 0, 0, 4 |
objects_wave 500, 4000, 0, 30, 0, 0 |
objects_wave 400, 400, 3, 5, 15, 0 |
objects_wave 400, 400, 0, 0, 10, 0 |
objects_wave 0, -1, 0, 0, 0, 0 ; end of level |
end if |
|
;*********************************** |
; In game keyboard |
;*********************************** |
|
newlocend: |
mov [pathtime],0 |
inc [levelpart] |
jmp no_nextloc |
ingame_keyboard: |
window_get_key ; read key (eax=2) |
cmp al,0 |
jne this_is_hotkey |
; ah - contain scan code, al = 0 |
shl eax,16 |
shr eax,24 ; equal shr eax,8 + and eax,0x0FF |
; eax - contain scan code |
|
endgame dd 0 |
objects dd 0 |
endtest: |
cmp dword [edi+8],0 |
jne no_free |
ret |
no_free: |
mov [endgame],0 |
inc [objects] |
ret |
cmp al,key_P+128 |
jne not_P_key_up_scan_code |
not [pause_on] |
not_P_key_up_scan_code: |
|
if debug_mode = 1 |
cmp al,key_E ; player hp = player hp / 2 |
jne no_hp_test |
shr [player_hp],1 |
no_hp_test: |
cmp al,key_A ; player hp = 10000 |
jne no_hp_up |
mov [player_hp],10000 |
no_hp_up: |
cmp al,key_W ; Run final screen |
je set_final_screen_window_from_call |
end if |
|
no_nextloc: |
mov [objects],0 |
mov [endgame],1 |
readmas objmas,endtest |
cmp [endgame],1 |
jne no_end_lev ;no_nextloc |
; Keyboard array update, needs sub state |
cmp al,01111111b |
ja key_released |
mov byte [keymap+eax],'1' ; If scan code of key down |
jmp key_pressed |
key_released: |
and al,01111111b |
mov byte [keymap+eax],0 ; If scan code of key up |
key_pressed: |
this_is_hotkey: |
ret |
|
mov ebp,[levelpart] |
shl ebp,5 |
add ebp,levels |
mov eax,[ebp+4] |
cmp eax,dword 0 |
je end_lev ;end of level |
cmp eax,dword -1 |
je end_gm ;end of game |
;********************** |
; Final screen process |
;********************** |
|
no_end_lev: |
set_final_screen_window_from_call: |
add esp,4 ; Remove call address from stack |
set_final_screen_window: |
lea edx,[menu_keyboard] |
mov ebx,1 |
lea ecx,[draw_final_screen_window] |
jmp set_draw_proc |
|
cmp [num5],dword 0 |
je no_addsh |
cmp [ctime],dword 0 |
jne no_addsh |
cmp [lazer],dword 0 |
je no_addsh |
findmas massive,findzero |
;in edi off to free element |
jc close_app |
mov eax,[shipx] |
mov [edi],eax |
mov eax,[shipy] |
mov [edi+4],eax |
mov [edi+8],dword 1 ;show |
mov [edi+12],dword 0 |
mov [edi+16],dword -12 |
mov [ctime],dword 8 ;wait for cannon |
dec [lazer] |
no_addsh: |
you_won_text: db 'YOU WON!',0 |
|
cmp [num8],dword 0 |
je no_addplx |
cmp [xtime],dword 256-16 |
jae no_addplx |
cmp [plazma],0 |
je no_addplx |
findmas massive,findzero |
;in edi off to free element |
jc close_app |
mov eax,[shipx] |
mov [edi],eax |
mov eax,[shipy] |
mov [edi+4],eax |
mov [edi+8],dword 2 ;show |
add [xtime],dword 8 ;wait for cannon |
cmp [xtime],dword 256 |
jna okx |
mov [xtime],256 |
okx: |
mov [edi+12],dword 0 ;wait for cannon |
mov [edi+16],dword -8 ;wait for cannon |
dec [plazma] |
no_addplx: |
draw_final_screen_window: |
draw_image 5,24,canvas |
logo_font_size equ 5 |
logo_x = 5+(screen_w/2)-(6*logo_font_size*8/2) |
logo_y = screen_h/16*5 |
draw_label logo_x,logo_y,you_won_text,cl_White+((logo_font_size-1) shl 24) |
;image_draw_label canvas,200,8,'YOU WON!',cl_White |
draw_button 5,(screen_w/2)-40+5,300,80,14,'BACK TO MENU',cl_DarkRed,cl_Black |
|
clear_buffer canvas+8,canvas_end-canvas-8,7 |
|
image_draw_acimage canvas,ship_img,(screen_w/2)-16,220,cl_Black |
array_processing particles,draw_particles |
array_processing particles,move_particles ; move particles |
array_processing particles,remove_outofscr_particles ; del_outscreen_particles |
|
cmp [num2],dword 0 |
je no_addsh2 |
cmp [xtime],dword 0 |
jne no_addsh2 |
cmp [plazma],0 |
je no_addsh2 |
mov eax,[shipy] |
mov [temp3],eax |
mov [temp2],dword 5 |
loox2: |
mov [temp],dword 10 |
loox: |
findmas massive,findzero |
;in edi off to free element |
try_to_make_firework: |
inc [next_wave_timer] |
cmp [next_wave_timer],30 |
jna no_firework |
mov [next_wave_timer],0 ; reset firework timer before make firework |
random screen_w-60,eax |
mov ebx,eax |
random screen_h-60,eax |
mov edx,eax |
mov ecx,8 ; how much particles make in one fire explode |
next_star: |
array_find particles,find_empty_object |
jc close_app |
random 25,eax |
mov ebp,eax |
sub eax,12 |
add eax,[shipx] |
mov [edi],eax |
shr ebp,3 |
random ebp,eax |
neg eax |
add eax,[temp3] ;[shipy] |
mov [edi+4],eax |
mov [edi+8],dword 2 ;show hstar |
mov [edi],ebx ; random x position |
mov [edi+4],edx ; random y position |
mov [edi+8],dword 3 ; type of partice = 3. final screen particle |
rerand: |
random 5,eax |
sub eax,2 |
mov [edi+12],eax ;show hstar |
jz rerand ; eax = -2...2 exclude 0 |
mov [edi+12],eax ; x velocity |
rerand2: |
random 7,eax |
sub eax,8 |
mov [edi+16],eax ;show hstar |
dec [temp] |
jnz loox |
sub [temp3],30 |
dec [temp2] |
jnz loox2 |
mov [xtime],dword 256 ;wait for cannon |
sub [plazma],50 |
no_addsh2: |
sub eax,3 |
jz rerand2 ; eax = -3...3 exclude 0 |
mov [edi+16],eax ; y velocity |
dec ecx |
jnz next_star |
no_firework: |
ret |
|
;*********************** |
; Help menu |
;*********************** |
|
cmp [num1],dword 0 |
je no_left |
sub dword [shipx],6 |
no_left: |
set_help_window: |
lea edx,[menu_keyboard] |
mov ebx,-1 |
lea ecx,[draw_help_window] |
jmp set_draw_proc |
|
cmp [num3],dword 0 |
je no_right |
add dword [shipx],6 |
no_right: |
draw_help_window: |
; draw background and gray rectangle for label |
;draw_frect canvas size cl_Black |
draw_frect 40,50,580,380,cl_Grey |
|
;ship correct |
cmp [shipx],5 |
jnl xl_ok |
mov [shipx],5 |
xl_ok: |
cmp [shipx],603 |
jng xr_ok |
mov [shipx],603 |
xr_ok: |
; draw labels |
mov ebp,4*7+3 ; Set value to labels counter |
mov ebx,180*65536+90 |
mov edx,helptext |
mov esi,50 |
mov ecx,cl_White+(10000000b shl 24) |
draw_next_string: |
mov eax,4 |
mcall ; Draw label |
@@: |
mov al,[edx] ; Loop for find next zero |
inc edx |
cmp al,0 |
jne @b |
|
add ebx,10 ; Incrase y position of label |
dec ebp ; Decrase labels counter |
jnz draw_next_string |
|
;clear scrbuf |
mov edi,canvas+8 |
cld |
mov ecx,640*440*3/4 |
mov eax,0 |
rep stosd |
; draw images of space objects |
mov eax,90 |
mov ecx,7 |
@@: |
mov esi,[(img_offset-4)+ecx*4] |
pushad |
draw_image 90,eax,esi |
popad |
add eax,40 |
dec ecx |
jnz @b |
|
compmas objmas,massive,compobr |
draw_button 5,500,400,80,14,'< BACK',cl_DarkRed,cl_Black |
ret |
|
readmas objmas,shipobjtest |
readmas massive,shipguntest |
; Offset to images showed in help screen in reverse sequence |
img_offset: |
dd box_img,asteroid_img,gwarship_img,bwarship_img |
dd plasma1_img,laser_img,ship_img |
|
readmas objmas,showobjmas |
readmas objmas,moveobjmas |
helptext: |
db 'Phoenix - player ship',0 |
db 'Controls:',0 |
db 'Left or Right Arrows for move ship, P - button for pause',0 |
db 0 |
db 'Laser gun',0 |
db 'Recharge fast, speed fast. Projectile speed is medium',0 |
db 'Press Space button for shoot',0 |
db 0 |
db 'Plasma gun',0 |
db 'Recharge slow, reload fast. Projectile speed is fast',0 |
db 'Press Up button for shoot or Down button for make Nuke',0 |
db 0 |
db 'Blue warship',0 |
db 'Moving speed is fast',0 |
db 'Armed with plasma bombs',0 |
db 0 |
db 'Green warship',0 |
db 'Moving speed is medium',0 |
db 'Armed with laser gun',0 |
db 0 |
db 'Asteroid',0 |
db 'Is not destructable dangeros object!',0 |
db 'Collision with asteroid damage ship to much',0 |
db 0 |
db 'Repear Box',0 |
db 'Shield pack. Shield +5, Score +30',0 |
db 'Take on board for shield level up!',0 |
db 0,0,0 |
db 'Developed by Pavlushin Evgeni 2004',0 |
|
readmas massive,showmas |
readmas massive,movemas |
readmas massive,delfarshoot |
; findmas massive,findzero |
;in edi off to free element |
; jc close_app |
; **************************************** |
; GLOBAL DRAW WINDOW |
; **************************************** |
|
aimgtoimg ship,[shipx],[shipy],canvas,0x0 |
draw_window: |
window_begin_draw |
mcall 0, <40, screen_w+9>, <40, screen_h+24+4>, 0x14000000,, wtitle |
window_end_draw |
ret |
|
drawfbox 150,5,64,5,0x000000 |
mov eax,[xtime] |
sub eax,256 |
neg eax |
shr eax,2 |
drawfbox 150,5,eax,5,0x0000ff |
; **************************************** |
; GAME PROCEDURE AREA |
; **************************************** |
|
drawfbox 150,12,64,5,0x000000 |
mov eax,[ctime] |
sub eax,8 |
; Procedure for add ships to scene |
; cl - number of ships which need to add 0..255 |
; ebp - offset to level string |
add_objects: |
; unpack values from ebx |
xor eax,eax |
mov al,ch |
mov [shiptype],eax |
mov al,bl |
mov [yaccel],eax |
mov al,bh |
mov [ymoving],eax |
shr ebx,16 |
mov al,bl |
mov [xaccel],eax |
mov al,bh |
mov [xmoving],eax |
next_ship: |
cmp cl,0 |
je no_ships ; if ships quantity = 0, exit from proc |
push ecx |
push ebp |
; find empty slot in space objects array |
array_find objects,find_empty_object |
jc close_app |
; edi = offset to empty place in array |
mov eax,[shiptype] |
mov dword [edi+8],eax ; store ship type |
; Randomize x position |
random screen_w-32,eax |
mov [edi],eax |
; Randomize y position |
pop ebp |
mov ax,[ebp+2] ; get max range |
cwde ; extend ax to eax |
random eax,eax |
neg eax |
shl eax,3 |
drawfbox 150,12,eax,5,0xffff00 |
mov [edi+4],eax |
; Randomize x moving |
random [xmoving],eax |
sub eax,[xaccel] |
mov [edi+12],eax |
; Randomize y moving |
random [ymoving],eax |
add eax,[yaccel] |
mov [edi+16],eax |
pop ecx |
dec cl |
jnz next_ship |
no_ships: |
ret |
|
drawfbox 220,2,6*5+2 ,9,cl_Grey |
outcount [plazma],221,3,cl_Blue,5*65536 |
drawfbox 220,11,6*5+2 ,9,cl_Grey |
outcount [lazer],221,12,0xffff00,5*65536 |
; search empty slot in object array |
find_empty_object: |
cmp [edi+8],dword 0 ; if object type == 0 then it empty |
je is_finded ; empty object is finded set CF = 0 |
; find_next |
stc ; CF = 1 |
ret |
is_finded: |
clc ; CF = 0 |
ret |
|
; Try to draw particle from particle array |
draw_particles: |
mov ecx,[edi+8] ; ecx - type of particle |
cmp ecx,0 ; if type == 0 then do not draw object |
je return |
mov eax,laser_img |
cmp ecx,Laser ; this is laser particle |
je draw_space_object |
mov eax,plasma2_img |
cmp ecx,StaticPlasma ; particle type for final screen animation |
je draw_space_object |
random 3,ebx ; if else this is Plasma particle |
mov eax,plasma1_img |
dec ebx |
jz draw_space_object |
mov eax,plasma2_img |
dec ebx |
jz draw_space_object |
mov eax,plasma3_img |
jmp draw_space_object |
|
drawfbox 280,6,6*5+2 ,9,cl_Grey |
outcount [gship],281,7,cl_Green,5*65536 |
drawfbox 320,6,6*5+2 ,9,cl_Grey |
outcount [bship],321,7,cl_Blue,5*65536 |
drawfbox 360,6,6*5+2 ,9,cl_Grey |
outcount [boxget],361,7,0xffaa00,5*65536 |
; Draw space objects from array |
draw_objects: |
mov ecx,[edi+8] ; ecx = [edi+8] - type of ship |
cmp ecx,0 ; if type of ship == 0 then not draw it |
je return |
cmp ecx,(ot_end-object_type)/4+1 |
jae return ; if type out of range ignore it |
mov edx,[edi+4] ; edx = [edi+4] - y position of ship |
cmp edx,screen_h-40 |
jg return |
cmp edx,0 ; do not draw object if it y position is out of screen |
jl return |
mov eax,[(object_type-4)+ecx*4] ; -4 when types starts from 1 instead 0 |
draw_space_object: |
image_draw_acimage canvas,eax,dword [edi],dword [edi+4],cl_Black |
return: |
ret |
|
drawfbox 400,2,6*5+2 ,9,cl_Grey |
outcount [objects],401,2,0x00ff00,5*65536 |
drawfbox 400,11,6*5+2 ,9,cl_Grey |
outcount [energy],401,12,0xff0000,5*65536 |
object_type: dd bwarship_img,gwarship_img,asteroid_img,box_img |
ot_end: |
|
drawfbox 450,11,6*5+2 ,9,cl_Grey |
outcount [score],451,12,0xffff00,5*65536 |
; Update (move) particles (laser,plasma) |
move_particles: |
xor eax,eax |
cmp [edi+8],eax ; Is object not empty ? |
je this_is_empty_particle |
move_particle: |
mov eax,[edi+12] |
add [edi],eax ; objectx + [edi+12] |
mov eax,[edi+16] |
add [edi+4],eax ; objecty + [edi+16] |
this_is_empty_particle: |
ret |
|
; update (move) space objects (ships,asteroids,boxes) |
move_objects: |
xor eax,eax |
cmp [edi+8],eax |
je object_is_empty |
;call move_particle |
mov eax,[edi+12] |
add [edi],eax |
mov eax,[edi+16] |
add [edi+4],eax |
|
jmp still |
; Do not allow object to go out of screen from right side |
mov eax,screen_w-32 ; eax = right side of screen |
cmp dword [edi],eax |
jng right_side_ok |
mov dword [edi],eax |
neg dword [edi+12] |
jmp left_side_ok |
right_side_ok: |
; Do not allow object to go out of screen from left side |
xor eax,eax ; eax = 0 - left side of screen |
cmp dword [edi],eax |
jnl left_side_ok |
mov dword [edi],eax |
neg dword [edi+12] |
left_side_ok: |
; If object out of screen remove it |
cmp dword [edi+4],screen_h;-40 |
jng y_ok |
mov dword [edi+8],0 ; Delete object |
ret |
y_ok: |
cmp dword [edi+8],GreenWarShip ; Object is green enemy ship? |
jne no_grs |
mov eax,dword [edi+4] ; eax = y position of enemy ship |
; alternative way is use random for shoot |
cmp eax,100 |
jna no_grs |
cmp eax,103 |
jna grs |
cmp eax,200 |
jna no_grs |
cmp eax,203 |
jna grs |
cmp eax,300 |
jna no_grs |
cmp eax,303 |
ja no_grs |
grs: |
; invert y moving direction and make shoot |
neg dword [edi+12] |
mov [temp],edi |
array_find particles,find_empty_object |
jc close_app |
mov esi,[temp] ; edi contains address to free element |
mov [edi+8],dword 1 |
mov [edi+12],dword 0 |
mov [edi+16],dword 10 |
jmp set_particle_position |
no_grs: |
cmp dword [edi+8],BlueWarShip ; object is blue enemy ship ? |
jne no_bls |
mov ecx,dword [edi+4] |
cmp ecx,50 |
jna no_bls |
cmp ecx,64 |
jna bls |
cmp ecx,100 |
jna no_bls |
cmp ecx,114 |
jna bls |
cmp ecx,150 |
jna no_bls |
cmp ecx,164 |
ja no_bls |
bls: |
; drop plasma mine |
mov [temp],edi |
array_find particles,find_empty_object |
jc close_app |
mov esi,[temp] |
mov [edi+8],dword 2 |
mov [edi+12],dword 0 |
mov [edi+16],dword 5 |
set_particle_position: |
mov eax,[esi] |
mov [edi],eax ; Particle x = Ship x |
mov eax,[esi+4] |
mov [edi+4],eax ; Partcle y = Ship y |
no_bls: |
object_is_empty: |
ret |
|
red: |
call draw_window |
jmp still |
; Remove particles that have gone out off screen |
remove_outofscr_particles: |
cmp dword [edi+4],40 ; test y position |
jl del |
cmp dword [edi+4],screen_h-40 |
jg del |
cmp dword [edi],0 ; x test used for plasma shoots |
jl del |
cmp dword [edi],screen_w-32 |
jg del |
ret ; do not delete |
del: |
xor eax,eax |
mov [edi+8],eax ; [edi+8] = 0 |
not_del: |
ret |
|
key: ; key |
mov eax,2 |
mcall ; read (eax=2) |
objects_and_particles_hit_handling: |
xor eax,eax |
cmp [esi+8],eax |
je no_hit |
cmp [edi+8],eax ; If object is empty skip crush test |
je no_hit |
cmp [esi+16],eax |
jg no_hit |
|
shr eax,8 |
and eax,0xff |
mov ah,al |
mov eax,[esi] |
shl eax,16 |
mov ax,word [esi+4] |
mov ebx,32*65536+32 |
mov ecx,[edi] |
shl ecx,16 |
mov cx,word [edi+4] |
mov edx,32*65536+32 |
|
cmp ah,153 |
jne no_pause |
not [pause_on] |
jmp still |
no_pause: |
game_collision_2d eax,ebx,ecx,edx |
jnc no_hit |
|
|
cmp ah,76 |
jne no_num5d |
mov [num5],1 |
jmp still |
no_num5d: |
cmp ah,204 |
jne no_num5u |
mov [num5],0 |
jmp still |
no_num5u: |
|
cmp ah,80 |
jne no_num2d |
mov [num2],1 |
jmp still |
no_num2d: |
cmp ah,208 |
jne no_num2u |
mov [num2],0 |
jmp still |
no_num2u: |
|
cmp ah,79 ;key_Space 85 exit |
jne no_num1d |
mov [num1],1 |
jmp still |
no_num1d: |
cmp ah,207 ;key_Space 85 exit |
jne no_num1u |
mov [num1],0 |
jmp still |
no_num1u: |
|
cmp ah,81 ;key_Space 85 exit |
jne no_num3d |
mov [num3],1 |
jmp still |
no_num3d: |
cmp ah,209 ;key_Space 85 exit |
jne no_num3u |
mov [num3],0 |
jmp still |
no_num3u: |
|
cmp ah,72 ;key_Space 85 exit |
jne no_num8d |
mov [num8],1 |
jmp still |
no_num8d: |
cmp ah,200 ;key_Space 85 exit |
jne no_num8u |
mov [num8],0 |
jmp still |
no_num8u: |
|
jmp still ; not testing |
|
button: ; button |
mov eax,17 ; get id |
mcall |
cmp ah,1 ; button id=1 ? |
jne noclose |
close_app: |
mov eax,-1 ; close this program |
mcall |
noclose: |
jmp still |
|
draw_window: |
|
mcall 12,1 ;start window redraw |
mcall 0, <40, 640+9>, <40, 440+26>, 0x14000000,, wtitle |
mcall 12,2 ;end window redraw |
; setimg 5,22,img_area |
|
cmp dword [edi+8],GreenWarShip |
jne not_grship |
inc [gships_destroyed] |
add [score],30 |
jmp remove_object_and_particle |
not_grship: |
cmp dword [edi+8],BlueWarShip |
jne not_blship |
inc [bships_destroyed] |
add [score],20 |
jmp remove_object_and_particle |
not_blship: |
cmp dword [edi+8],Asteroid |
jne not_asteroid |
cmp dword [edi+16],1 ; Asteroid have minimal speed? |
je remove_only_particle |
dec dword [edi+16] ; Decrase speed of asteroid |
jmp remove_only_particle |
not_asteroid: |
remove_object_and_particle: ; When hit to ship or box |
mov [edi+8],dword 0 |
remove_only_particle: ; When hit to asteroid |
mov [esi+8],dword 0 |
no_hit: |
ret |
|
;********************** |
; Game Over process |
;********************** |
player_and_objects_collision_handling: |
cmp [edi+8],dword 0 |
je no_obj_cr |
|
game_over: |
; close |
call draw_gowindow |
stillgo: |
wtevent redgo,keygo,buttongo |
jmp stillgo |
redgo: |
call draw_gowindow |
jmp stillgo |
keygo: |
mov eax,2 |
mcall |
jmp stillgo |
buttongo: |
mov eax,17 ; get id |
mcall |
cmp ah,1 |
je close_app |
cmp ah,4 |
je close_app |
cmp ah,5 |
je main_menu |
cmp ah,7 |
je restart_lev |
jmp stillgo |
mov eax,[shipx] |
shl eax,16 |
mov ax,word [shipy] |
mov ebx,32*65536+32 |
mov ecx,[edi] |
shl ecx,16 |
mov cx,word [edi+4] |
mov edx,32*65536+32 |
|
restart_lev: |
mov [pathtime],0 |
|
prevpart: |
mov ebp,[levelpart] |
shl ebp,5 |
add ebp,levels |
mov eax,[ebp] |
cmp eax,dword 1 |
je rest ;end of level |
dec [levelpart] |
jmp prevpart |
|
|
rest: |
;massives reset - clear massives |
mov edi,massive+8 |
cld |
mov ecx,massize*elemsize/4 |
mov eax,0 |
rep stosd |
|
mov edi,objmas+8 |
cld |
mov ecx,omassize*oelemsize/4 |
mov eax,0 |
rep stosd |
|
;counters reset |
mov [boxget],0 |
mov [gship],0 |
mov [bship],0 |
|
;ship reset |
mov [energy],100 |
mov [shipx],300 |
mov [shipy],400 |
mov [lazer],1000 |
mov [plazma],500 |
|
|
; reset keyboard |
mov [num1],0 |
mov [num5],0 |
mov [num3],0 |
mov [num2],0 |
mov [num8],0 |
jmp start_game |
|
draw_gowindow: |
startwd |
call draw_window |
mcall 9,proc_info,-1 |
test [proc_info+process_information.wnd_state], 0x04 |
jz @f |
game_collision_2d eax,ebx,ecx,edx |
jnc no_obj_cr |
cmp dword [edi+8],Box ; if box |
jne no_fbox |
add [player_hp],5 |
add [score],50 |
mov [edi+8],dword 0 ; delete object |
inc [boxes_taken] |
ret |
@@: |
drawfbox 170,160,300,120,cl_Grey |
drawlbut 180,260,80,14,'EXIT',4,0x990000,cl_Black |
drawlbut 280,260,80,14,'MENU',5,0x990000,cl_Black |
drawlbut 380,260,80,14,'RESTART',7,0x990000,cl_Black |
|
label 280,200,' GAME OVER ',cl_Black |
endwd |
no_fbox: |
sub [player_hp],16 |
mov [edi+8],dword 0 ; delete object |
no_obj_cr: |
ret |
|
player_and_particles_collision_handling: |
xor eax,eax ; use eax as zero |
cmp [edi+8],eax ; empty object? |
je no_gobj_cr |
cmp [edi+16],eax ; is player ? |
jl no_gobj_cr |
|
;********************** |
; End level process |
;********************** |
mov eax,[shipx] |
shl eax,16 |
mov ax,word [shipy] |
mov ebx,32*65536+32 |
mov ecx,[edi] |
shl ecx,16 |
mov cx,word [edi+4] |
mov edx,32*65536+32 |
|
end_lev: |
; close |
call draw_scorewindow |
stilleg: |
wtevent redeg,keyeg,buttoneg |
jmp stilleg |
redeg: |
call draw_scorewindow |
jmp stilleg |
keyeg: |
mov eax,2 |
mcall |
jmp stilleg |
buttoneg: |
mov eax,17 ; get id |
mcall |
cmp ah,1 |
je close_app |
cmp ah,2 |
je next_lev |
cmp ah,3 |
je help |
cmp ah,4 |
je close_app |
cmp ah,5 |
je main_menu |
jmp stilleg |
game_collision_2d eax,ebx,ecx,edx |
jnc no_gobj_cr |
sub [player_hp],4 |
mov [edi+8],dword 0 ; delete object |
no_gobj_cr: |
ret |
|
next_lev: |
mov [pathtime],0 |
inc [levelpart] |
;************************** |
; Player ship shoot procs |
;************************** |
|
;ship reset |
mov [energy],100 |
mov [shipx],300 |
mov [shipy],400 |
mov [lazer],1000 |
mov [plazma],500 |
|
;counters reset |
mov [boxget],0 |
mov [gship],0 |
mov [bship],0 |
|
; reset keyboard |
mov [num1],0 |
mov [num5],0 |
mov [num3],0 |
mov [num2],0 |
mov [num8],0 |
jmp start_game |
|
draw_scorewindow: |
call draw_window |
mcall 9,proc_info,-1 |
test [proc_info+process_information.wnd_state], 0x04 |
jz @f |
; Try to make laser shoot |
try_to_make_laser_shoot: |
cmp [laser_charge],dword 0 |
jne no_laser_shoot ; laser_shoots is heat, need time for recharge |
cmp [laser_shoots],dword 0 |
je no_laser_shoot ; Don't shoot when so many laser particles on screen |
array_find particles,find_empty_object ; edi = offset to emppty object |
jc close_app ; ? |
mov eax,[shipx] |
mov [edi],eax ; 0 = x position of shoot |
mov eax,[shipy] |
mov [edi+4],eax ; 4 = y position of shoot |
mov [edi+8],dword 1 ; 8 = 1 - laser type |
mov [edi+12],dword 0 ; 12 = 0 - x speed |
mov [edi+16],dword -12 ; 16 = -12 - y speed |
mov [laser_charge],dword 8 ; Reset shoot timer |
dec [laser_shoots] ; Decrase number of laser projectiles |
no_laser_shoot: |
ret |
@@: |
startwd |
drawfbox 170,130,300,190,cl_Grey |
drawlbut 180,300,80,14,'(X) EXIT',4,0x990000,cl_Black |
drawlbut 280,300,80,14,'<MENU>',5,0x990000,cl_Black |
drawlbut 380,300,80,14,'NEXT >>',2,0x990000,cl_Black |
|
setimg 180,140,warship1 |
outcount [bship],241,151,cl_Blue,5*65536 |
|
setimg 180,180,warship2 |
outcount [gship],241,191,cl_Green,5*65536 |
|
setimg 180,220,meteor |
setimg 180,260,box |
outcount [boxget],241,271,0xbbbb00,5*65536 |
endwd |
; Try to make plasma shoot |
try_to_make_plasma_shoot: |
cmp [plasma_charge],dword 256-16 |
jae no_plasma_shoot |
cmp [plasma_shoots],0 |
je no_plasma_shoot |
array_find particles,find_empty_object |
; edi = off to free element |
jc close_app ;? |
mov eax,[shipx] |
mov [edi],eax |
mov eax,[shipy] |
mov [edi+4],eax |
mov [edi+8],dword 2 ; 8 = 2 - plasma |
mov [edi+12],dword 0 ; 12 = 0 - x speed |
mov [edi+16],dword -8 ; 16 = -8 - y speed |
dec [plasma_shoots] ; Decrase number of plasma projectiles |
add [plasma_charge],dword 8 |
cmp [plasma_charge],dword 256 |
jna no_plasma_shoot |
mov [plasma_charge],256 |
no_plasma_shoot: |
ret |
|
|
;********************** |
; End of game process |
;********************** |
|
end_gm: |
mov [pathtime],0 |
call draw_window |
label 200 ,8,'YOU WIN PRESS ANY KEY TO EXIT',cl_White+font_Big |
|
stilleg2: |
; scevent redeg2,keyeg2,buttoneg2 |
timeevent 1,no_event2,redeg2,keyeg2,buttoneg2 |
|
no_event2: |
setimg 5,21,canvas |
|
;clear scrbuf |
mov edi,canvas+8 |
cld |
mov ecx,640*440*3/4 |
mov eax,0 |
rep stosd |
|
aimgtoimg ship,320,220,canvas,0x0 |
|
readmas massive,endshowmas |
readmas massive,endmovemas |
readmas massive,delfarshoot |
; findmas massive,findzero |
;in edi off to free element |
; jc close_app |
|
inc [pathtime] |
cmp [pathtime],30 |
jne no_firework |
mov [pathtime],0 |
random 400,eax |
; Try to make plasma nuke |
try_to_make_plasma_nuke: |
xor eax,eax ; Use eax as zero |
cmp [plasma_charge],eax |
jne no_plasma_nuke |
cmp [plasma_shoots],eax |
je no_plasma_nuke |
mov eax,[shipy] |
mov [temp3],eax |
random 600,eax |
mov [temp2],eax |
mov [temp],dword 8;10 |
xloox: |
findmas massive,findzero |
;in edi off to free element |
mov [temp2],dword 5 |
loopx2: |
mov [temp],dword 10 |
loopx: |
array_find particles,find_empty_object ; edi = offset to empty element |
jc close_app |
|
mov eax,[temp2] ;[shipx] |
mov [edi],eax |
mov eax,[temp3] ;[shipy] |
random 25,eax |
mov ebp,eax |
sub ebp,12 |
add ebp,[shipx] |
mov [edi],ebp ; [edi] = random(0..25)-12+shipx |
shr eax,3 |
random eax,eax |
neg eax |
add eax,[temp3] |
mov [edi+4],eax |
mov [edi+8],dword 2 ;show hstar |
rerand: |
mov [edi+8],dword 2 ; 8 = 2 - plasma |
random 5,eax |
sub eax,2 |
cmp eax,0 |
je rerand |
mov [edi+12],eax ;show hstar |
rerand2: |
mov [edi+12],eax |
random 7,eax |
sub eax,3 |
cmp eax,0 |
je rerand2 |
mov [edi+16],eax ;show hstar |
sub eax,8 |
mov [edi+16],eax |
dec [temp] |
jnz xloox |
no_firework: |
jmp stilleg2 |
jnz loopx |
sub [temp3],30 ; shipy - 30 |
dec [temp2] |
jnz loopx2 |
mov [plasma_charge],dword 256 ; Wait for cannon |
sub [plasma_shoots],50 ; -50 plasma bullets after nuke |
no_plasma_nuke: |
ret |
|
redeg2: |
jmp end_gm ;stilleg2 |
keyeg2: |
mov eax,2 |
mcall |
jmp main_menu |
buttoneg2: |
mov eax,17 ; get id |
mcall |
jmp stilleg2 |
; DATA AREA |
IM_END: |
wtitle db 'Phoenix for KOS', 0 |
|
score dd 0 ; player score |
|
; Pause state, if != 0 then game on pause |
pause_on dd 0 |
|
; Frames countdown timer until start of next wave |
; If = 0 then activate to next wave |
; next_wave_timer |
next_wave_timer dd 0 |
|
;gif_file_area ~21500 |
;gif_file_area2: |
;file 'phoenix.gif' |
gif_file_area: |
file 'objects.gif' ; Include gif file to code |
|
IncludeUGlobals |
|
; DATA AREA |
IM_END: |
;global |
pause_on dd 0 |
; Window drawing function delegate (pointer) |
draw_proc rd 1 |
; Keyboard processing function delegate (pointer) |
keyboard_proc rd 1 |
|
;massive |
shipx dd 300 |
shipy dd 400 |
; Counter of objects on screen |
objects_num rd 1 |
|
player_hp rd 1 ; Health points of player ship |
shipx rd 1 ; Player ship x position |
shipy rd 1 ; Player ship y position |
;guns |
lazer dd 1000 |
plazma dd 500 |
laser_shoots rd 1 ; laser bullets quantity |
plasma_shoots rd 1 ; plasma bullets quantity |
; Counters of player statistics |
gships_destroyed rd 1 ; Number of green ships destroyed by player |
bships_destroyed rd 1 ; Number of blue ships destroyed by player |
boxes_taken rd 1 ; Number of repair boxes taken by player |
; Gun recharge counters |
; 0 = fully charged |
; 256 = fully uncharged |
laser_charge rd 1 ; Laser gun recharge counter |
plasma_charge rd 1 ; Plasma gun recharge counter |
|
;keys |
num1 dd 0 |
num5 dd 0 |
num3 dd 0 |
num2 dd 0 |
num8 dd 0 |
; Tempory varibles |
temp rd 1 |
temp2 rd 1 |
temp3 rd 1 |
|
;enemy countres |
gship dd 0 |
bship dd 0 |
boxget dd 0 |
event_mode rd 1 ; if -1 wait, 0 scan, n - n delay between events |
|
energy dd 100 |
score dd 0 |
; Tempory varibles for add_objects proc |
shiptype rd 1 |
xmoving rd 1 |
ymoving rd 1 |
xaccel rd 1 |
yaccel rd 1 |
|
;delay for cannon |
ctime dd 0 |
;delay for nuke gun |
xtime dd 0 |
;path time |
pathtime dd 0 |
; |
temp dd 0 |
temp2 dd 0 |
temp3 dd 0 |
temp4 dd 0 |
otv dd 0 |
; Memory for contain not splitted image |
objects_image: rb 8+288*32*3 ;8+256*64*3 |
; Images sequence extracted from objects_image |
ship_img: rb 8+32*32*3 ; Player red space ship |
laser_img: rb 8+32*32*3 ; Double laser beams |
bwarship_img: rb 8+32*32*3 ; Blue enemy ship |
gwarship_img: rb 8+32*32*3 ; Green enemy ship |
asteroid_img: rb 8+32*32*3 ; Space asteroid |
plasma1_img: rb 8+32*32*3 ; Plasma big flash |
plasma2_img: rb 8+32*32*3 ; Plasma medium flash |
plasma3_img: rb 8+32*32*3 ; Plasma small flash |
box_img: rb 8+32*32*3 ; Repear kit box |
|
;for collimg |
imgsize: |
dd 32 |
dd 32 |
; array for storing state of keyboard keys |
keymap: rb 128 |
|
;massive: |
;dd 400 ;elements num |
;dd 20 ;size of element in bytes |
;rb 400*20 |
particles: |
rd max_particles ; dword = maximum number of particle objects |
rd particle_size ; dword = size of each particle object in bytes |
rb max_particles*particle_size |
|
keymap: |
rb 1000 |
objects: |
rd max_objects ; dword = maximum number of particles |
rd object_size ; dword = size of each object in bytes |
rb max_objects*object_size |
|
wtitle db 'Phenix for KolibriOS', 0 |
|
;gif_file_area ~21500 |
gif_file_area2: |
file 'phenix.gif' |
gif_file_area: |
file 'star2.gif';include gif file |
img_area: |
rb 256*64*3+8 |
ship: |
rb 32*32*3+8 |
shoot: |
rb 32*32*3+8 |
warship1: |
rb 32*32*3+8 |
warship2: |
rb 32*32*3+8 |
meteor: |
rb 32*32*3+8 |
star: |
rb 32*32*3+8 |
star2: |
rb 32*32*3+8 |
star3: |
rb 32*32*3+8 |
box: |
rb 32*32*3+8 |
|
IncludeUGlobals |
|
massive: |
rd massize ;elements num |
rd elemsize ;size of element in bytes |
rb massize*elemsize |
|
objmas: |
rd omassize ;elements num |
rd oelemsize ;size of element in bytes |
rb omassize*oelemsize |
|
canvas: |
canvas_x: |
rd 1 |
canvas_y: |
rd 1 |
rb (640*440*3)+2000 |
rb 8+(screen_w*screen_h*3) |
canvas_end: |
|
proc_info: |
rb 1024 |
I_END: |
; application stack size |
align 16 |
stack_max: |
rb 2048 |
I_END: |