Skip to content

Instantly share code, notes, and snippets.

@dugagjin
Created January 9, 2016 14:14
Show Gist options
  • Save dugagjin/7fb95d11b644a39dfeab to your computer and use it in GitHub Desktop.
Save dugagjin/7fb95d11b644a39dfeab to your computer and use it in GitHub Desktop.
basic FlappyBird clone in x86 32 bit assembly dosbox protected mode MASM syntax
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "draw.inc"
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
DATASEG
bottomGrass = 170 ; position grass in Y
topGround = 180 ; positon ground in Y
; color defined by the bios color attributes
colorPipes = 2
colorSky = 11
colorGrass = 10
colorGround = 6
colorBodyBird = 14 ; color yellow
colorLipsBird = 12 ; color red
colorWhite = 15 ; color white
colorBlack = 0 ; color black
pipesDistance = 30 ; pipe gate distance
pipeLarge = 25 ; define how large pipes are
; pipes coordinates, respectivly pipe 1,2 3
; we give here parameter to start drawing pipe from left
; we also give the parameter to hight of gate pipes
pipeOneXleft = 280
pipeOneXright = pipeLarge + pipeOneXleft
pipeOneYupper = 50
pipeOneYbottom = pipesDistance + pipeOneYupper
pipeTwoXleft = 66
pipeTwoXright = pipeLarge + pipeTwoXleft
pipeTwoYupper = 80
pipeTwoYbottom = pipesDistance + pipeTwoYupper
pipeThreeXleft = 162
pipeThreeXright = pipeLarge + pipeThreeXleft
pipeThreeYupper = 30
pipeThreeYbottom = pipesDistance + pipeThreeYupper
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; CODE
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
CODESEG
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; DRAW BACKGROUND (SKY, GRASS AND GROUND)
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC drawWorld
pusha
mov cx, 0 ; start drawing x position = 0
mov dx, 0 ; start drawing y position = 0
mov al, colorSky ; draw sky blue (color is 11)
@@drawBackgroundLayer:
int 10h ; call BIOS service to draw the pixel
inc cx ; go one pixel right
cmp cx, 320 ; look if we did draw all 320 horizontal pixels
jl @@drawBackgroundLayer ; if not: continue drawing horizontaly until we reached the last horizontal pixel to the right
inc dx ; if we did: jump one pixel under in order to draw the next horizontal line
mov cx, 0 ; we reset our pixel to the first one to the left
cmp dx, bottomGrass ; look if we arrived to y = 150
jl @@drawBackgroundLayer ; if not: continue drawing verticaly until we reached y = 150
mov al, colorGrass ; if we did: change color to green (color is = 10)
cmp dx, topGround ; look if we arrived to y = 160 (if whole grass terrain is colored or not)
jl @@drawBackgroundLayer ; if not: continue the same loop as for the sky
mov al, colorGround ; if we did then change color to brown (color is = 6)
cmp dx, 200 ; continue drawing ground until the end (y = 200)
jl @@drawBackgroundLayer ; if we did reach y = 200 (everything is colored) then function is ended
popa
ret
ENDP drawWorld
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; DRAW THE WHOLE PIPES
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC drawPipes
ARG startPosX:word, endPosX:word, upperGate:word, bottomGate:word
; we our arguments with cx and dx and we get 4 arguments:
; - left x position where we start drawing
; - right x position where we end the drawing
; - height position y of the upper part of the pipe
; - height position y of the bottom part of the pipe
pusha
mov cx, [startPosX] ; start drawing in x from left wehere assigned to
mov dx, 0 ; pipe drawing start always at y = 0 from
mov al, colorPipes ; we choose color dark green (color = 2)
@@drawPipesLayer:
int 10h ; draw the pixel
inc cx ; move 1 pixel to the right
cmp cx, [endPosX] ; Are we arrived to the last horizontal pixel?
jl @@drawPipesLayer ; if not: continue drawing horizontaly
inc dx ; if yes: go down in y with one pixel
mov cx, [startPosX] ; reset the horizontal drawing to the to the first pixel on the left
cmp dx, [upperGate] ; did we reach the y = position of the upper part of the pipe?
jl @@drawPipesLayer ; if not: continue drawing
jg @@jump ; if we did then jump from drawing y = upperGate to y = bottomGate
mov dx, [bottomGate] ; (jump needed otherwise stuck at 100)
@@jump: ; continue drawing from y = bottomGate to the end (y = 150)
cmp dx, bottomGrass
jl @@drawPipesLayer
popa
ret
ENDP drawPipes
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; ANIM PIPES BY REMOVING VERTICAL LEFT LINE
; AND ADDING IT TO THE LEFT
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC animPipes
; the idea is simple: we remove on line of vertical pixels of the pipe.
; this line is on the left. We remove it by remplacing the color of the pipe by the color of the sky.
; we add one vertical line to the right with the same color as the pipe.
; this creates a effect of movement.
call animPipesFunction, pipeOneXleft, pipeOneYupper, pipeOneYbottom, colorSky ; send parameters to remove left side
call animPipesFunction, pipeOneXright, pipeOneYupper, pipeOneYbottom, colorPipes ; send parameters to add right side
call animPipesFunction, pipeTwoXleft, pipeTwoYupper, pipeTwoYbottom, colorSky ; send parameters to remove left side
call animPipesFunction, pipeTwoXright, pipeTwoYupper, pipeTwoYbottom, colorPipes ; send parameters to add right side
call animPipesFunction, pipeThreeXleft, pipeThreeYupper, pipeThreeYbottom, colorSky ; send parameters to remove left side
call animPipesFunction, pipeThreeXright, pipeThreeYupper, pipeThreeYbottom, colorPipes ; send parameters to add right side
call slide ; to shift the pipes place
ret
ENDP animPipes
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; SHIFT PIPES BY ONE FOR EVERY TIME MAIN LOOP IS DONE
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC slide
cmp edi, 2 ; we compare with the loop counter.
jl @@Loopke ; we do it 1 times per 2 loops otherwise the pipes are moving too fast
add bx, 1 ; shift pipes to right by 1. When to the left we restart by substracting 320
cmp bx, 320
jl @@doNotResetValue
sub bx, 320
@@doNotResetValue:
@@Loopke:
ret
ENDP slide
PROC animPipesFunction
ARG startPosXleft:word, pipeTop:word, pipeDown:word, kleur:byte
pusha
mov al, [kleur] ; set color to draw
mov cx, [startPosXleft] ; define start position to start drawing
add cx, bx ; modify position to make a "movement"
mov dx, 0 ; define start position in y to start drawing
@@animPipesLayer:
int 10h ; call BIOS interrupt to draw the pixel
inc cx ; move one pixel to the right
cmp cx, [startPosXleft + 1] ; because we want just to draw one vertical line we directly jump back to default
jl @@animPipesLayer
inc dx ; we go one line under
mov cx, [startPosXleft] ; like we said above, we jump cx back to default
add cx, bx
cmp dx, [pipeTop] ; we do this until the end of the upperpipe
jl @@animPipesLayer
cmp dx, [pipeDown] ; if end of the upper pipe is reached we jump to the bottom pipe
jg @@jump
mov dx, [pipeDown]
@@jump:
cmp dx, bottomGrass ; we continue remplacing vertical lines until we arrived to the end
jl @@animPipesLayer
popa
ret
ENDP animPipesFunction
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; DRAW BIRD BY HORIZONTAL LINE. SEND WHERE START AND WHERE
; TO END + COLOR. INCREMENT DX TO DRAW LINE UNDER
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC drawBird
call drawBirdFunction, 256, 261, colorBlack
inc dx
call drawBirdFunction, 255, 255, colorBlack
call drawBirdFunction, 256, 256, colorWhite
call drawBirdFunction, 257, 257, colorBlack
call drawBirdFunction, 258, 261, colorBodyBird
call drawBirdFunction, 261, 263, colorBlack
inc dx
call drawBirdFunction, 254, 254, colorBlack
call drawBirdFunction, 255, 258, colorWhite
call drawBirdFunction, 258, 258, colorBlack
call drawBirdFunction, 259, 263, colorBodyBird
call drawBirdFunction, 263, 263, colorBlack
inc dx
call drawBirdFunction, 253, 253, colorBlack
call drawBirdFunction, 254, 254, colorWhite
call drawBirdFunction, 255, 255, colorBlack
call drawBirdFunction, 256, 258, colorWhite
call drawBirdFunction, 258, 258, colorBlack
call drawBirdFunction, 259, 262, colorBodyBird
call drawBirdFunction, 262, 266, colorBlack
inc dx
call drawBirdFunction, 253, 253, colorBlack
call drawBirdFunction, 254, 254, colorWhite
call drawBirdFunction, 255, 255, colorBlack
call drawBirdFunction, 256, 258, colorWhite
call drawBirdFunction, 258, 258, colorBlack
call drawBirdFunction, 259, 261, colorBodyBird
call drawBirdFunction, 261, 261, colorBlack
call drawBirdFunction, 262, 266, colorWhite
call drawBirdFunction, 266, 266, colorBlack
inc dx
call drawBirdFunction, 253, 253, colorBlack
call drawBirdFunction, 254, 257, colorWhite
call drawBirdFunction, 257, 257, colorBlack
call drawBirdFunction, 258, 260, colorBodyBird
call drawBirdFunction, 260, 260, colorBlack
call drawBirdFunction, 261, 266, colorWhite
call drawBirdFunction, 266, 266, colorBlack
inc dx
call drawBirdFunction, 251, 257, colorBlack
call drawBirdFunction, 257, 260, colorBodyBird
call drawBirdFunction, 260, 260, colorBlack
call drawBirdFunction, 261, 266, colorWhite
call drawBirdFunction, 266, 266, colorBlack
inc dx
call drawBirdFunction, 250, 250, colorBlack
call drawBirdFunction, 251, 257, colorLipsBird
call drawBirdFunction, 257, 257, colorBlack
call drawBirdFunction, 258, 261, colorBodyBird
call drawBirdFunction, 261, 261, colorBlack
call drawBirdFunction, 262, 265, colorWhite
call drawBirdFunction, 265, 265, colorBlack
inc dx
call drawBirdFunction, 251, 257, colorBlack
call drawBirdFunction, 257, 257, colorLipsBird
call drawBirdFunction, 258, 258, colorBlack
call drawBirdFunction, 259, 262, colorBodyBird
call drawBirdFunction, 262, 265, colorBlack
inc dx
call drawBirdFunction, 251, 251, colorBlack
call drawBirdFunction, 252, 257, colorLipsBird
call drawBirdFunction, 257, 257, colorBlack
call drawBirdFunction, 258, 264, colorBodyBird
call drawBirdFunction, 264, 264, colorBlack
inc dx
call drawBirdFunction, 252, 257, colorBlack
call drawBirdFunction, 257, 262, colorBodyBird
call drawBirdFunction, 262, 264, colorBlack
inc dx
call drawBirdFunction, 257,262, colorBlack
sub dx, 11 ; we reset DX position as it was before the drawBird
ret
ENDP drawBird
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; THIS DRAWS FROM LEFT TO RIGHT. GIVE VALUE FOR X START
; AND X BEGIN. + COLOR.
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC drawBirdFunction
ARG begin:word, ending:word, kleurVogel:byte
USES cx
mov al, [kleurVogel] ; gives color
mov cx, [begin] ; give start place in x
@@drawBirdLayer:
int 10h ; call BIOS service to color pixel
inc cx ; shift place to draw to one pixel right
cmp cx, [ending] ; look if we are at the end
jl @@drawBirdLayer ; if so then stop drawing
ret
ENDP drawBirdFunction
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; SIMILAR METHOD AS FOR DRAWING BIRD BUT THIS CLEANS IT
; JUST GIVE X BEGIN AND X END PLACE TO CLEAN
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC cleanPreviousBird
call cleanBirdFunction, 256, 262
call cleanBirdFunction, 255, 264
call cleanBirdFunction, 254, 264
call cleanBirdFunction, 253, 267
call cleanBirdFunction, 253, 267
call cleanBirdFunction, 253, 267
call cleanBirdFunction, 251, 267
call cleanBirdFunction, 250, 266
call cleanBirdFunction, 251, 266
call cleanBirdFunction, 251, 265
call cleanBirdFunction, 252, 265
call cleanBirdFunction, 257, 263
sub dx, 12 ; we reset DX position as it was before the drawBird
ret
ENDP cleanPreviousBird
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; JUST BEGIN AND END POSITION ARE NEEDED. NO COLOR
; COLOR IS IN FUNCTION ITSELF BECAUSE ALWAYS = COLOR SKY
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC cleanBirdFunction
ARG begin:word, ending:word
USES cx
mov al, colorSky ; gives color (here sky color)
mov cx, [begin] ; gives start place to draw
@@drawBirdLayer:
int 10h ; call BIOS service to color pixel
inc cx ; shift place to draw to one pixel right
cmp cx, [ending] ; look if we are at the end
jl @@drawBirdLayer ; if so then stop drawing
inc dx ; go to next horizontal line
ret
ENDP cleanBirdFunction
END
GLOBAL drawWorld:PROC, \
drawPipes:PROC, \
animPipes:PROC, \
slide:PROC, \
drawBird:PROC, \
cleanPreviousBird:PROC, \
cleanPreviousBirdFunction:PROC, \
drawBirdFunction:PROC, \
animPipesFunction:PROC
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; 32-bit Assembly game
; Made by lashi Dugagjin & Quentin Quevy
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "vga.inc"
include "text.inc"
include "world.inc"
include "draw.inc"
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; DATA
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
DATASEG
birdPos = 70 ; place were bird starts
gravityPower = 3 ; lower = greater gravity
pipesDistance = 30 ; pipe gate distance
pipeLarge = 25 ; define how large pipes are
; pipes coordinates, respectivly pipe 1,2 3
; we give here parameter to start drawing pipe from left
; we also give the parameter to hight of gate pipes
pipeOneXleft = 280
pipeOneXright = pipeLarge + pipeOneXleft
pipeOneYupper = 50
pipeOneYbottom = pipesDistance + pipeOneYupper
pipeTwoXleft = 66
pipeTwoXright = pipeLarge + pipeTwoXleft
pipeTwoYupper = 80
pipeTwoYbottom = pipesDistance + pipeTwoYupper
pipeThreeXleft = 162
pipeThreeXright = pipeLarge + pipeThreeXleft
pipeThreeYupper = 30
pipeThreeYbottom = pipesDistance + pipeThreeYupper
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; CODE
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
CODESEG
PROC main
call setVideoMode
mov ah, 0Ch ; function 0Ch to start the draw mode with int 10h
call drawWorld ; draw the background (sky, grass and ground)
; draw the pipes
call drawPipes, pipeOneXleft, pipeOneXright, pipeOneYupper, pipeOneYbottom
call drawPipes, pipeTwoXleft, pipeTwoXright, pipeTwoYupper, pipeTwoYbottom
call drawPipes, pipeThreeXleft, pipeThreeXright, pipeThreeYupper, pipeThreeYbottom
mov bx, 0 ; set value start value shift the pipes (start from 0)
mov dx, birdPos ; set value start where bird is drawed
mov edi, 0 ; set start value loop for gravity (normaly always 0)
push edi
@@mainLoop:
call drawBird ; draw the bird
call animPipes ; move the pipes to the right
call updateWorld ; wait for vertical retrace
; GRAVITY BEGIN
pop edi
inc edi ; this a loop to slower down gravity. We count to 3. When 3 is reached then
cmp edi, gravityPower ; we draw the bird a little bit under where he was.
jl @@Loop ; when 3 is not reached we move on, we do not mov the bird position
call cleanPreviousBird
inc dx ; increment (change bird position one pixel lower) when edi reached 3.
mov edi, 0 ; if gravity did affect then reset counter
@@Loop:
push edi
; GRAVITY END
call birdDied ; check if bird died if so this function will end the game
call procesUserInput ; if game is not endend we check for user input en restart the loop.
jmp @@mainLoop
@@endOfLoop:
call setTextMode ; function that quits the game
ENDP main
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; STACK
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
STACK 1000h
END main
# =============================================================================
# Project makefile
# =============================================================================
# Settings
objs = text.obj vga.obj draw.obj world.obj main.obj
dest = main.exe
# =============================================================================
# Do NOT edit this section, unless you know what you are doing.
# =============================================================================
.asm.obj
tasm /ml /m2 /w2 /z /zi /p /jIDEAL $<
$(dest): $(objs)
wlink option quiet system pmodew name $@ file {$(objs)}
clean: .symbolic
del *.obj
del $(dest)
.silent
debug: $(objs) .symbolic
wlink debug watcom lines option Q,C system pmodew name $(dest) file {$(objs)}
wd /tr=rsi /li=43 $(dest)
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "text.inc"
include "draw.inc"
include "world.inc"
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; CODE
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
CODESEG
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; SET TEXT MODE
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC setTextMode
mov ax,3h ; specify AH=0 (set video)
int 10h ; call VGA BIOS
mov eax, 4c00h ; AH = 4Ch - Exit To DOS
int 21h
ret
ENDP setTextMode
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; INPUT USER
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC procesUserInput
; get user input. If space is pressed then bird goes above
; if nothing is pressed then nothing happens
pusha
mov ah, 01h ; look if there is anything in the keyboard buffer
int 16h
jz @@end ; if the keyboard buffer is 0 then jump to end
mov ah, 00h ; if keyboard buffer is free then read user input
int 16h
cmp al, ' ' ; if user pressed the spacebar?
jne @@end ; if not: jump to end (nothing happens)
popa
call cleanPreviousBird ; if bird moves, the old one has to be cleaned of the screen
sub dx, 12 ; if so then make bird jump by 9 pixels above
pusha
call sound, 4000 ; play sound corresponding to 4000.
@@end:
popa
ret
ENDP procesUserInput
END
GLOBAL setTextMode:PROC, \
procesUserInput:PROC
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "vga.inc"
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; CODE
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
CODESEG
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; SET VIDEO MODE 320x200
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC setVideoMode
pusha
mov ax,13h ; specify AH=0 (set video)
int 10h ; call VGA BIOS
popa
ret
ENDP setVideoMode
END
GLOBAL setVideoMode:PROC
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "world.inc"
include "text.inc"
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; DATASEG
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
DATASEG
CollisionXleft = 246
CollisionXright = 270
offsetBirdInY = 12
detectColorPipe = 2
detectColorGrass = 10
detectColorGround = 6
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
; CODE
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
CODESEG
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; VERTICAL RETRACE METHOD
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
PROC updateWorld
pusha
mov dx, 03dah ; vga status port
@@waitVBlank_wait1: ; if already in VB, then wait until it is finished
in al, dx ; read status
and al, 8 ; test bit
jnz @@waitVBlank_wait1 ; busy waiting if in VB
@@waitVBlank_wait2: ; wait until begin of a new VB
in al, dx ; read status
and al, 8 ; test bit
jz @@waitVBlank_wait2 ; busy wait if not in VB
popa
ret
ENDP updateWorld
PROC birdDied
mov ah, 0Dh ; we activate the function to read pixels color at a given place x = cx and y = dx
call checkCollision, CollisionXleft,0,detectColorPipe ; if touched pipes with head left side
call checkCollision, CollisionXleft, offsetBirdInY,detectColorPipe ; if touched pipes with head down left side
call checkCollision, CollisionXright,0,detectColorPipe ; if touched pipes with head right side
call checkCollision, CollisionXright, offsetBirdInY, detectColorPipe ; if touched pipes with head down right side
call checkCollision, CollisionXright - 8, offsetBirdInY + 5, detectColorGrass ; if touched floor (grass)
call checkCollision, CollisionXleft, 0, detectColorGround ; if fly too high (out of screen)
mov ah, 0Ch ; we desactivate the function to read pixels and go back in write pixel modus
ret
ENDP birdDied
PROC checkCollision
ARG placeX:word, placeY:word, kleur:byte
mov cx, [placeX] ; go to x coordinate
add dx, [placeY] ; go to y coordinate relative to bird
int 10h ; read color
sub dx, [placeY] ; reset relative position to bird
cmp al, [kleur] ; compare color if it is the same the color that we want to detect nearby or bird
jne @@doNotEndGame ; if yes then end game if not continue game
call sound, 5000 ; if not then end game but before play some sound
call sound, 6000
call setTextMode ; we end game and set text mode back
@@doNotEndGame:
ret
ENDP checkCollision
PROC sound
ARG freq:word
USES ax
mov al, 182 ; prepare the speaker for the note
out 43h, al
mov ax, [freq] ; frequency number in decimar
out 42h, al ; output low byte
mov al, ah ; output high byte
out 42h, al
in al, 61h ; turn on note (get value from port 61h)
or al, 00000011b ; set bits 1 and 0
out 61h, al ; send new value
mov bx, 3 ; break for duration of note
@@break1: ; we doe some breaks to limit sound duration
mov cx, 65535
@@break2:
dec cx
jne @@break2
dec bx
jne @@break1
in al, 61h ; turn off note (get value from port 61h)
and al, 11111100b ; reset bits 1 and 0
out 61h, al ; send new value
ret
ENDP sound
END
GLOBAL updateWorld:PROC, \
birdDied:PROC, \
checkCollision:PROC, \
sound:PROC, \
gravity:PROC
@abeerstupid
Copy link

abeerstupid commented Dec 8, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment