kolibrios/programs/games/snake/trunk/level.asm

849 lines
21 KiB
NASM
Raw Permalink Normal View History

;;===Level_mode================================================================================================================
Level_begin:
call Load_level
call Get_eat
mcall 66,1,1 ; set scan codes mode for keyboard
Level_body:
;;===Level_body========================================================================================================
call Hide_cursor
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
.redraw:
call Set_geometry
mcall 12,1
mcall 0, , ,[window_style], ,window_title
test [proc_info.wnd_state], 0x04 ; is rolled up?
jnz Pause_mode
call Draw_decorations
call Draw_stones
call Draw_snake
call Draw_eat
call Draw_level_strings
mcall 12,2
.still:
mcall 26, 9
push eax
sub eax, [time_before_waiting]
pop [time_before_waiting]
cmp [time_to_wait], eax
jg @f
cmp [action], 0
jne Game_step
@@:
sub [time_to_wait], eax
mcall 23, [time_to_wait] ;
test al, al
jnz @f
cmp [action], 0
jne Game_step
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
jmp .still
@@:
.message: ; ok, what an event?
dec al ; has the window been moved or resized?
jz .redraw ;
dec al ; was a key pressed?
jz .key ;
dec al ; was a button pressed?
jz .button ;
.button: ; <20><><EFBFBD><EFBFBD><E6A5A4><EFBFBD> <20><><EFBFBD><E0A0A1><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>ணࠬ<E0AEA3><E0A0AC>
mcall 17 ; <20><EFBFBD><E3ADAA><EFBFBD> 17: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
shr eax, 8 ; ᤢ<><E1A4A2><EFBFBD><EFBFBD><EFBFBD><><E0A5A3><EFBFBD><EFBFBD> eax <20><> 8 <20><><EFBFBD> <20><><EFBFBD>, <20><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cmp eax, 1
je Save_do_smth_else_and_exit
jmp .still
.key:
mcall 2 ; get keycode
;pushf
;pusha
;movzx eax, ah
;dph eax
;newline
;popa
;popf
cmp ah, 0x01 ; Escape
je First_menu
cmp ah, 0x39 ; Space
je Pause_mode
cmp ah, 0x4B ; Left
je .key.left
cmp ah, [shortcut_move_left] ; Left
je .key.left
cmp ah, 0x50 ; Down
je .key.down
cmp ah, [shortcut_move_down] ; Down
je .key.down
cmp ah, 0x48 ; Up
je .key.up
cmp ah, [shortcut_move_up] ; Up
je .key.up
cmp ah, 0x4D ; Right
je .key.right
cmp ah, [shortcut_move_right] ; Right
je .key.right
cmp ah, 0x4B+0x80 ; Left released
je .key.released.left
mov al, [shortcut_move_left]
add al, 0x80
cmp ah, al ; Left released
je .key.released.left
cmp ah, 0x50+0x80 ; Down released
je .key.released.down
mov al, [shortcut_move_down]
add al, 0x80
cmp ah, al ; Down released
je .key.released.down
cmp ah, 0x48+0x80 ; Up released
je .key.released.up
mov al, [shortcut_move_up]
add al, 0x80
cmp ah, al ; Up released
je .key.released.up
cmp ah, 0x4D+0x80 ; Right released
je .key.released.right
mov al, [shortcut_move_right]
add al, 0x80
cmp ah, al ; Right released
je .key.released.right
cmp ah, [shortcut_reverse]
jne @f
call Reverse_snake
jmp .still
@@:
cmp ah, [shortcut_increase]
jne @f
call Increase_geometry
jmp .redraw
@@:
cmp ah, [shortcut_decrease]
jne @f
call Decrease_geometry
jmp .redraw
@@:
jmp .still ; jump to wait for another event
.key.left:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], RIGHT
je .still
@@:
mov [snake_direction_next], LEFT
bts [acceleration_mask], LEFT
jc Game_step
jmp .still
.key.down:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], UP
je .still
@@:
mov [snake_direction_next], DOWN
bts [acceleration_mask], DOWN
jc Game_step
jmp .still
.key.up:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], DOWN
je .still
@@:
mov [snake_direction_next], UP
bts [acceleration_mask], UP
jc Game_step
jmp .still
.key.right:
bts [action], 0
jc @f
mov [time_to_wait], 0
@@:
cmp [smart_reverse], 1
jne @f
cmp [snake_direction], LEFT
je .still
@@:
mov [snake_direction_next], RIGHT
bts [acceleration_mask], RIGHT
jc Game_step
jmp .still
.key.released.left:
btr [acceleration_mask], LEFT
jmp .still
.key.released.down:
btr [acceleration_mask], DOWN
jmp .still
.key.released.up:
btr [acceleration_mask], UP
jmp .still
.key.released.right:
btr [acceleration_mask], RIGHT
jmp .still
Game_step:
cmp [snake_direction], LEFT ; are we moving to left?
jz .left
cmp [snake_direction], DOWN ; ... down?
jz .down
cmp [snake_direction], UP ; ... up?
jz .up
jmp .right ; then right
.left:
cmp [snake_direction_next], RIGHT ; next step is to right?
jz .with_reverse
jmp .without_reverse
.down:
cmp [snake_direction_next], UP ; next step is to up?
jz .with_reverse
jmp .without_reverse
.up:
cmp [snake_direction_next], DOWN ; next step is to bottom?
jz .with_reverse
jmp .without_reverse
.right:
cmp [snake_direction_next], LEFT ; next step is to left?
jz .with_reverse
jmp .without_reverse
.with_reverse:
call Set_reverse_direction
call Reverse
.without_reverse:
mov edx, snake_dots-2
add edx, [snake_length_x2]
cmp [snake_direction_next], LEFT
je .to_left
cmp [snake_direction_next], DOWN
je .to_down
cmp [snake_direction_next], UP
je .to_up
cmp [snake_direction_next], RIGHT
je .to_right
.to_left:
mov [snake_direction], LEFT
mov ax, [edx]
dec al
cmp al, -1
jne @f
mov al, GRID_WIDTH
dec al
@@:
jmp Snake_move
.to_down:
mov [snake_direction], DOWN
mov ax, [edx]
inc ah
cmp ah, GRID_HEIGHT
jne @f
mov ah, 0
@@:
jmp Snake_move
.to_up:
mov [snake_direction], UP
mov ax, [edx]
dec ah
cmp ah, -1
jne @f
mov ah, GRID_HEIGHT
dec ah
@@:
jmp Snake_move
.to_right:
mov [snake_direction], RIGHT
mov ax, [edx]
inc al
cmp al, GRID_WIDTH
jne @f
mov al, 0
@@:
jmp Snake_move
;;---Level_body--------------------------------------------------------------------------------------------------------
;;---Level_mode----------------------------------------------------------------------------------------------------------------
;;===Some_functions============================================================================================================
Draw_snake:
;;===Draw_snake========================================================================================================
call Draw_head_prehead
mov edx, [snake_color]
mov esi, snake_dots-6
add esi, [snake_length_x2]
@@:
mov bx, [esi]
sub esi, 2
call Draw_square
cmp esi, snake_dots-2
jne @b
ret
;;---Draw_snake--------------------------------------------------------------------------------------------------------
Draw_head_prehead:
;;===Draw_head_prehead=================================================================================================
mov edx, [snake_head_color]
mov esi, snake_dots-2
add esi, [snake_length_x2]
mov bx, [esi]
call Draw_square
sub esi, 2
mov bx, [esi]
mov edx, [snake_color]
call Draw_square
call Draw_lives_in_head
ret
;;---Draw_head_prehead-------------------------------------------------------------------------------------------------
Draw_level_strings:
;;===Draw_level_strings================================================================================================
mov ebx, [window_width]
shr ebx, 1
sub ebx, string_pause_space.size*3+6
shl ebx, 16
add ebx, [top_strings]
mcall 4, ,[navigation_strings_color],string_pause_space ; Draw 'PAUSE - SPACE' string
; call Draw_menu_esc
call Draw_score_string
call Draw_score_number ; Draw score (number)
call Draw_champion_string
call Draw_champion_name
call Draw_hiscore_string
call Draw_hiscore_number
cmp [play_mode], LEVELS_MODE
jne @f
mov ebx, [window_width]
shr ebx, 3
sub ebx, 5
shl ebx, 16
add ebx, [bottom_bottom_strings]
mcall 4, ,[level_string_color],string_level
mov edx, [window_width]
shr edx, 3
sub edx, 5+1
add edx, string_level.size*6
shl edx, 16
add edx, [bottom_bottom_strings]
mcall 47,0x00020000,[cur_level_number], ,[level_number_color],[background_color]
@@:
ret
;;---Draw_level_strings------------------------------------------------------------------------------------------------
Reverse:
;;===Reverse===========================================================================================================
mov ecx, [snake_length_x2]
shr ecx, 2
mov esi, snake_dots
mov edi, snake_dots-2
add edi, [snake_length_x2]
@@:
mov ax, [edi]
xchg ax, [esi]
mov [edi], ax
add esi, 2
sub edi, 2
dec cx
jnz @b
ret
;;---Reverse-----------------------------------------------------------------------------------------------------------
Draw_eat:
;;===Draw_eat==========================================================================================================
mov bx, word[eat]
mov edx, [eat_color]
call Draw_square
ret
;;---Draw_eat----------------------------------------------------------------------------------------------------------
Get_eat:
;;===Get_eat===========================================================================================================
;; in :
;;
;; out :
;; ax = coord's of the eat square (al=x, ah=y)
;;
mcall 26,9
; xor eax, esp
shl eax, 1
xor edx, edx
div word[number_of_free_dots]
mov ebx, field_map
.loop:
cmp byte[ebx], 0
jne @f
test dx, dx
jz .place_found
dec dx
@@:
inc ebx
jmp .loop
.place_found:
sub ebx, field_map
mov eax, ebx
mov bl, GRID_WIDTH
div bl
xchg al, ah
mov word[eat], ax
ret
;;---Get_eat-----------------------------------------------------------------------------------------------------------
Sdvig:
;;===Sdvig=============================================================================================================
mov esi, snake_dots+2
mov edi, snake_dots
mov ecx, [snake_length_x2]
shr ecx, 1
cld
rep movsw
ret
;;---Sdvig-------------------------------------------------------------------------------------------------------------
Set_reverse_direction:
;;===Set_reverse_direction==================================================================================================
mov eax, snake_dots
mov ebx, snake_dots+2
mov cl, [eax] ; The last dot x_coord
mov ch, [ebx] ; The pre_last dot x_coord
cmp cl, ch
je .X_ravny
cmp cl, 0
jne .skip2
mov dl, GRID_WIDTH
dec dl
cmp ch, dl
jne .Normal_y_ravny
mov [snake_direction_next], RIGHT
ret
.skip2:
mov dl, GRID_WIDTH
dec dl
cmp cl, dl
jne .Normal_y_ravny
cmp ch, 0
jne .Normal_y_ravny
mov [snake_direction_next], LEFT
ret
.Normal_y_ravny:
cmp cl, ch
jg .Napravlenie_to_right
mov [snake_direction_next], LEFT
ret
.Napravlenie_to_right:
mov [snake_direction_next], RIGHT
ret
.X_ravny:
inc eax
inc ebx
mov cl, [eax]
mov ch, [ebx]
cmp cl, 0
jne .skip3
mov dl, GRID_HEIGHT
dec dl
cmp ch, dl
jne .Normal_x_ravny
mov [snake_direction_next], DOWN
ret
.skip3:
mov dl, GRID_HEIGHT
dec dl
cmp ch, dl
jne .Normal_x_ravny
cmp ch, 0
jne .Normal_x_ravny
mov [snake_direction_next], UP
ret
.Normal_x_ravny:
cmp cl, ch ; !!!
jg .Napravlenie_to_down ; 0 1 2 ...
mov [snake_direction_next], UP ; 1
ret ; 2
; .
.Napravlenie_to_down: ; .
mov [snake_direction_next], DOWN ; .
ret
;;---Set_reverse_direction--------------------------------------------------------------------------------------------------
Snake_move:
;;===Snake_move=============================================================================================================
;; in :
;; ax = coord's of new head
;; edx = snake_dots+[snake_length_x2]-2 (snake head)
;;
add edx, 2
mov [edx], ax
cmp ax, word[eat]
jne .eat_and_new_head_are_different
add [snake_length_x2], 2
add [score], SCORE_EAT
dec [number_of_free_dots]
cmp [number_of_free_dots], 0
je Game_over
mov ax, word[eat]
mov cl, 1
call Draw_on_map
call Draw_head_prehead
cmp [play_mode], CLASSIC_MODE
jne .is_not_classic_mode
dec byte[speed_up_counter]
jns @f
mov al, byte[speed_up_counter+1]
mov byte[speed_up_counter], al
cmp [time_wait_limit], 4
jl @f
dec [time_wait_limit]
@@:
.is_not_classic_mode:
cmp [play_mode], LEVELS_MODE
jne .is_not_levels_mode
cmp [snake_length_x2], (EAT_TO_END_LEVEL+3)*2
je .skip
.is_not_levels_mode:
call Get_eat
call Draw_eat
.skip:
jmp Keys_done
.eat_and_new_head_are_different:
push ax
mov ax, word[snake_dots]
mov cl, 0
call Draw_on_map
pop ax
call Get_from_map
test bl, bl
jnz Game_over
mov cl, 1
call Draw_on_map
mov bx, word[snake_dots]
mov edx, [background_color]
call Draw_square
call Sdvig
call Draw_head_prehead
Keys_done:
cmp [score], 0
je @f
dec [score]
call Draw_score_number
@@:
cmp [play_mode], LEVELS_MODE
jne @f
cmp [snake_length_x2], (EAT_TO_END_LEVEL+3)*2
je Do_smth_between_levels
@@:
mcall 26, 9
mov [time_before_waiting], eax
mov eax, [time_wait_limit]
mov [time_to_wait], eax
jmp Level_body.still
;;---Snake_move------------------------------------------------------------------------------------------------------------
Do_smth_between_levels:
;;===Do_smth_between_levels================================================================================================
inc [cur_level_number]
cmp [cur_level_number], LAST_LEVEL_NUMBER+1
jne @f
mov [cur_level_number], LEVELS_MODE_FIRST_LEVEL
@@:
call Draw_splash
@@:
mcall 2
cmp eax, 1
jne @b
jmp Level_begin
;;---Do_smth_between_levels------------------------------------------------------------------------------------------------
Draw_splash:
;;===Draw_splash===========================================================================================================
mov al, 0
mov cl, GRID_WIDTH-1
mov edx, [splash_background_color]
.draw:
mov bh, GRID_HEIGHT-1
mov bl, al
@@:
call Draw_square
sub bh, 2
cmp bh, 0
jg @b
inc al
mov bh, GRID_HEIGHT-2
mov bl, cl
@@:
call Draw_square
sub bh, 2
cmp bh, 0
jnl @b
dec cl
cmp cl, 0
jl .picture
push eax ebx
mcall 5,PAUSE_WHILE_DRAWING_SPLASH
mcall 2
cmp ah, 0x39 ; Space
jne @f
pop ebx eax
jmp .quit
@@:
cmp ah, 0x1C ; Enter
jne @f
pop ebx eax
jmp .quit
@@:
pop ebx eax
jmp .draw
.picture:
mov ax, 2*0x100+24
mov cx, 1*0x100+5
mov edx, [splash_level_string_color]
mov esi, picture_level
call Draw_picture
mov eax, [cur_level_number]
mov dl, 10
div dl
push ax
mov esi, digits_font
@@:
test al, al
jz @f
add esi, 5
dec al
jmp @b
@@:
mov ax, 9*0x100+4
mov cx, 8*0x100+5
mov edx, [splash_level_number_color]
call Draw_picture
pop ax
mov esi, digits_font
@@:
test ah, ah
jz @f
add esi, 5
dec ah
jmp @b
@@:
mov ax, 15*0x100+4
mov cx, 8*0x100+5
mov edx, [splash_level_number_color]
call Draw_picture
mcall 26,9
mov [time_before_waiting], eax
mov [time_to_wait], PAUSE_BETWEEN_LEVELS
@@:
mcall 23,[time_to_wait]
mcall 2
cmp ah, 0x39 ; Space
je .quit
cmp ah, 0x1C ; Enter
je .quit
mcall 26,9
push eax
sub eax, [time_before_waiting]
pop [time_before_waiting]
sub [time_to_wait], eax
jns @b
.quit:
ret
;;---Draw_splash-----------------------------------------------------------------------------------------------------------
Draw_lives_in_head:
;;===Draw_lives_in_head====================================================================================================
cmp [play_mode], LEVELS_MODE
jne .quit
test [show_lives_style], 2
jz .quit
mov eax, snake_dots-2
add eax, [snake_length_x2]
mov ax, word[eax]
mov bl, ah
mul byte[g_s]
mov edx, [gbxm1]
add dx, ax
shl edx, 16
mov al, bl
mul byte[g_s]
mov dx, word[gbym1]
add dx, ax
mov eax, [g_s]
shl eax, 16
add eax, [g_s]
and eax, 0xfffefffe
shr eax, 1
add edx, eax
sub edx, 0x00020003
mcall 47,0x80010001,lives,,[lives_in_head_number_color]
.quit:
ret
;;---Draw_lives_in_head----------------------------------------------------------------------------------------------------
;;---Some_functions------------------------------------------------------------------------------------------------------------