flat assembler
Message board for the users of flat assembler.

flat assembler > Examples and Tutorials > Sprite Fight Game: Animation, Sound+Music, Input

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
m3ntal



Joined: 08 Dec 2013
Posts: 296
Teaches animation, DirectSound load and play .WAV, simultaneous music+sound effects, X-Input (X360 controller) and/or keyboard, draw images inverted (to duplicate frames takes 200% memory), alpha effects, simulate shadows. Best viewed in 1366x768 resolution. Input: Move: Arrow keys, gamepad, left analog stick. Attack: A key or X button. Jump: S key or A button.

Uses sprites+music from the game Final Fight, (C) by CAPCOM (87). Many game programming students practice by using media from existing games.

Includes edited FASMW that allows optional ?if/?else/?repeat/etc for assembly directives and if/else/repeat/etc for runtime.

Download Sprite Fight

Video Preview: https://www.youtube.com/watch?v=0FJcDBSK53o


Excerpts:
Code:
  if can.jump
    if.gamepad B
      if.gamepad RIGHT
        go .jumpf
      end
      get.gamepad.lx
      if r0>4096
        go .jumpf
      end
      if.gamepad LEFT
        go .jumpb
      end
      get.gamepad.lx
      if r0<-4096
        go .jumpb
      end
      go .jumpu
    end
    if.keys S
      if.keys RIGHT
        .jumpf:
        animate player, JUMP, JUMPF, jumpf.a,\
         JUMP.SPEED, 0
        go .jumpe
      end
      if.keys LEFT
        .jumpb:
        animate player, JUMP, JUMPB, jumpb.a,\
         JUMP.SPEED, 0
        go .jumpe
      end
      .jumpu:
      animate player, JUMP, JUMPU, jumpu.a,\
       JUMP.SPEED, 0
      .jumpe:
      JUMP.HEIGHT=400
      . [player.state]=SS.JUMP
      . [player.ascend]='a'
      . r0=[player.y], [player.start.y]=r0
      . r0-JUMP.HEIGHT, [player.end.y]=r0
      go .paint
    end
  end

  if can.walk
    . walk?=NO
    . can.move.up=NO, can.move.down=NO
    . can.move.left=NO, can.move.right=NO
    . move.u=NO, move.d=NO
    . move.l=NO, move.r=NO

    if [player.y]>0
      . can.move.up=YES
    end
    . r0=[screen.h], r0-[player.h], r0-16
    if [player.y]<r0
      . can.move.down=YES
    end
    if [player.x]>0
      . can.move.left=YES
    end
    . r0=[screen.w], r0-[player.w]
    if [player.x]<r0
      . can.move.right=YES
    end

    SPEED.X=10
    SPEED.Y=8

    if can.move.up
      if.keys UP
        . move.u=YES
      end
      if.gamepad UP
        . move.u=YES
      end
      get.gamepad.ly
      if r0>4096
        . move.u=YES
      end
      if move.u
        . [player.y]-SPEED.Y, walk?=YES
      end
    end
    if can.move.down
      if.keys DOWN
        . move.d=YES
      end
      if.gamepad DOWN
        . move.d=YES
      end
      get.gamepad.ly
      if r0<-4096
        . move.d=YES
      end
      if move.d
        . [player.y]+SPEED.Y, walk?=YES
      end
    end
    if can.move.left
      if.keys LEFT
        . move.l=YES
      end
      if.gamepad LEFT
        . move.l=YES
      end
      get.gamepad.lx
      if r0<-4096
        . move.l=YES
      end
      if move.l
        . [player.x]-SPEED.X, walk?=YES
        . [player.invert.x]=YES
      end
    end
    if can.move.right
      if.keys RIGHT
        . move.r=YES
      end
      if.gamepad RIGHT
        . move.r=YES
      end
      get.gamepad.lx
      if r0>4096
        . move.r=YES
      end
      if move.r
        . [player.x]+SPEED.X, walk?=YES
        . [player.invert.x]=NO
      end
    end
    if walk?
      animate player, WALK, 0, walk.a, 4, 0
      go .paint
    end
  end

  ; get distance between player and enemy

  . face.enemy=NO
  . r0=[enemy.x], r1=[player.x]
  if r0<r1
    . r1-r0, dx=r1
    if [player.invert.x]
      . face.enemy=YES
    end
  else
    . r0-r1, dx=r0
    if not [player.invert.x]
      . face.enemy=YES
    end
  end
  . r0=[enemy.y], r1=[player.y]
  if r0<r1
    . r1-r0, dy=r1
  else
    . r0-r1, dy=r0
  end 

; adjectives: 1-7 scale

texts a7.ta[]= 'best', 'fastest', 'strongest',\
 'smartest', 'greatest', 'all'
texts a6.ta[]= 'better', 'faster', 'stronger',\
 'smarter', 'greater', 'most'
texts a5.ta[]= 'good', 'fast', 'strong',\
 'smart', 'great', 'more'
texts a4.ta[]= 'medium', 'average',\
 'normal', 'some'
texts a3.ta[]= 'weak', 'slow', 'dumb', 'less'
texts a2.ta[]= 'weaker', 'slower',\
 'dumber', 'lesser'
texts a1.ta[]= 'worst', 'weakest', 'slowest',\
 'dumbest', 'least', 'none'
                             
;;;;;;;;;;;;;;;;;;;; EFFECTS ;;;;;;;;;;;;;;;;;;;;;

; stars, explosions, lasers, projectiles

align

ARRAY effect.images[IMAGE]
integer effect.index, effect.count

EFFECT.SPEED=1

text effect.folder='EFFECT\'  ; SPRITE\EFFECT
texts effect.files[]=\
 '1', '2', '3', '4', '5'

function load.effects, scale
  locals i, n, image, file
  set.sprite.folder
  set.folder effect.folder    ; \EFFECT\
  . n=effect.files.$          ; # filenames
  try @size effect.images, n  ; allocate
 
  loop i=0 to n
    @ image=effect.images[i]
    . r0=i, file=[effect.files+r0*4]
    try load.image.t image, file
    try size.image.p image, scale
  endl
  . [effect.index]=0, [effect.count]=0
endf 1

function draw.effect, x, y
  locals i, n, image
  . i=[effect.index]
  . n=[effect.count]
  @ image=effect.images[i]
  draw.image image, x, y
  . n++
  if n>EFFECT.SPEED
    . i++
    . n=0
  end
  if i>=effect.files.$
    . i=0
  end
  . [effect.index]=i
  . [effect.count]=n
endf

; ?????????????????? SOUND.INC ???????????????????

structure SOUND
 void s, s2     ; PDIRECTSOUNDBUFFER[2]
 integer status
 boolean music, replay, playing, played
ends ?sound

; load .wav. return PDIRECTSOUNDBUFFER

function load.wav, file
  locale wav,\
   wav.data(20),\     ; MMCKINFO
   fmt.data(20),\     ; same
   wav.format(18),\   ; WAVEFORMATEX
   ds.desc(20),\      ; DSBUFFERDESC
   sound,\            ; PDIRECTSOUNDBUFFER
   audio1, audio2,\   ; circular buffers
   length1, length2   ; sizes

  . r0=&wav
  memory.zero r0, ..locals.size

  try wav=mmioOpenA file, 0, MMIO_ALLOCBUF

  . r0=&wav.data              ; find 'WAVE'
  . dword [r0+8]=45564157h
  mmioDescend wav,\
   r0, 0, MMIO_FINDRIFF

  . r0=&fmt.data              ; find 'fmt '
  . dword [r0+8]=20746D66h
  . r1=&wav.data
  mmioDescend wav, r0, r1, 0

  . r0=&wav.format
  mmioRead wav, r0, 18
  . r0=&fmt.data
  mmioAscend wav, r0, 0
  . r0=&fmt.data              ; find 'data'
  . dword [r0]=61746164h
  . r1=&wav.data
  mmioDescend wav,\
   r0, r1, MMIO_FINDCHUNK

  . r0=&ds.desc      ; sound buffer description
  . dword [r0]=20    ; size
  . dword [r0+4]=224 ; flags=DSBCAPS_CTRLDEFAULT
  . r1=&fmt.data
  . r1=[r1+4]        ; fmt.data.cksize
  . dword [r0+8]=r1  ; dwBufferBytes
  . r1=&wav.format
  . dword [r0+16]=r1 ; lpwfxFormat
  . r1=&sound
  callx [dsound],\   ; CreateSoundBuffer
   12, r0, r1, 0
  if true            ; error
    . sound=0
    jmp .close
  end
  . audio1=0
  . audio2=0         ; circular buffers
  push 0             ; IDirectSoundBuffer.Lock
  . r0=&length2
  push r0
  . r0=&audio2
  push r0
  . r0=&length1
  push r0
  . r0=&audio1
  push r0
  . r0=&fmt.data
  . r0=[r0+4]
  push r0
  push 0
  callx \
   sound, DS.Lock
  cmp audio1, 0      ; read from file
  jbe .us            ; write to sound buffers
  mmioRead wav,\
   audio1, length1
  .us:
  cmp audio2, 0
  jbe .us2
  mmioRead wav,\
   audio2, length2
  .us2:
  callx sound,\      ; IDirectSoundBuffer.Unlock
   DS.Unlock,\
   audio1, length1,\
   audio2, length2
  .close:
  mmioClose wav, 0
endf sound

; load "sound" effect (play once) or "music"
; (replay and allow simultaneous sounds
; to be playing in the background)

function load.sound, sound, file
  try load.wav file
  . r1=sound, [?sound.s+r1]=r0
endf 1

function load.music, sound, file
  try load.sound sound, file
  . r0=sound, r1=[?sound.s+r0]
  . r2=&[?sound.s2+r0]
  . [?sound.replay+r0]=1
  callx [dsound],\
   DS.DuplicateSoundBuffer, r1, r2
  if true
    return 0
  end
endf 1    


Description:
Filesize: 250.08 KB
Viewed: 4099 Time(s)

sprite_fight.jpg




Last edited by m3ntal on 08 Mar 2014, 19:58; edited 1 time in total
Post 12 Jan 2014, 03:47
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 720
Very good example - I didn't try to compile this on my machine; how long does it take fasm to process all of your macros?
Post 12 Jan 2014, 09:59
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
It builds fast, 1.5 seconds on my Z-Cube ITX for the library + game. See video preview.

Thanks to your examples I have decided to get back involved in game development.
Post 12 Jan 2014, 11:46
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 720
oh, that is fast. I downloaded it and played it, I just didn't try to compile it. Glad someone else is also posting game examples Very Happy
Post 12 Jan 2014, 12:43
View user's profile Send private message Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 5983
Location: Poland
I can't run this game on my machine with Windows 7 because it requests some functions from the 'XINPUT1_3.DLL' library.

One little remark: to make the shadows more realistic you need to slant it at some angle (SE direction for the right sprite and SW direction for the lest sprite). At least it seems to be like that accordingly to the perspective.
Post 12 Jan 2014, 14:57
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 720
maybe I should mention this tip to m3ntal,
In my geometry wars game, in order to play in on a computer without the gamepad driver installed, I used
Code:
                     invoke  LoadLibraryA,'XINPUT9_1_0.dll'
                       test  eax,eax
                         jz  @f
                     invoke  GetProcAddress,eax,'XInputGetState'
                       test  eax,eax
                         jz  @f
                        mov  [XInputGetState],eax
                @@:      

dword[XInputGetState] initially points to an empty function so that the rest of the game doesn't crash if if any of these api calls fail.
Post 12 Jan 2014, 15:10
View user's profile Send private message Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 5983
Location: Poland
tthsqe wrote:
maybe I should mention this tip to m3ntal,
In my geometry wars game, in order to play in on a computer without the gamepad driver installed, I used
Code:
                     invoke  LoadLibraryA,'XINPUT9_1_0.dll'
                       test  eax,eax
                         jz  @f
                     invoke  GetProcAddress,eax,'XInputGetState'
                       test  eax,eax
                         jz  @f
                        mov  [XInputGetState],eax
                @@:      

dword[XInputGetState] initially points to an empty function so that the rest of the game doesn't crash if if any of these api calls fail.
So, the existence of those XINPUT libraries isn't crucial for the game? It's good to know. I have never used gamepad as I am not especially interested in computer games. The only exceptions I make is when I want to check what the guys from this forum can code with FASM. Wink
Post 12 Jan 2014, 15:19
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 720
well, it of course depends on the programming, but I think any reasonable approach would not mind a call to XInputGetState not doing anything. Have you played the latest version of my geometry wars game with the keyboard? It will work whether or not xinput is installed.
Post 12 Jan 2014, 15:34
View user's profile Send private message Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 5983
Location: Poland
tthsqe wrote:
Have you played the latest version of my geometry wars game with the keyboard? It will work whether or not xinput is installed.
Yeah, sure, I played it, everything was OK. That's why I even didn't notice that the game can have such "exotic" libraries calls in its guts. Wink
Post 12 Jan 2014, 15:40
View user's profile Send private message Visit poster's website Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
Updated download to use LoadLibrary. It should not need X-Input now. XINPUT_GAMEPAD structures will be all zeros. Vibration works.
Post 12 Jan 2014, 19:50
View user's profile Send private message Reply with quote
MHajduk



Joined: 30 Mar 2006
Posts: 5983
Location: Poland
m3ntal wrote:
Updated download to use LoadLibrary. It should not need X-Input now. XINPUT_GAMEPAD structures will be all zeros. Vibration works.
Now it's OK but there was a situation when the sprite representing "Cody" went outside the screen area and there was no way to bring it back to the visible part of the screen with the cursor keys (although I could hear an action such as attack when I was pressing the A key). What can cause such a behavior? It shouldn't be a problem with the screen resolution because I have 1366x768, so what it could be?
Post 12 Jan 2014, 20:08
View user's profile Send private message Visit poster's website Reply with quote
HaHaAnonymous



Joined: 02 Dec 2012
Posts: 1174
Location: Unknown
Stupid post removed.


Last edited by HaHaAnonymous on 28 Feb 2015, 18:33; edited 1 time in total
Post 12 Jan 2014, 20:08
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
Quote:
Did you make all the graphics or you took them from other games?
Again, sprites Cody+Simons are from the game Final Fight by CAPCOM (87'). You can practice game programming by using graphics+sounds from existing games. Fair use: Non-profit, educational.


Last edited by m3ntal on 04 Feb 2014, 20:24; edited 1 time in total
Post 13 Jan 2014, 10:32
View user's profile Send private message Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 340
Location: Asia, Singapore
Nice, I guess we've had enough nerdy stuff, seriously something cool
like this was required Razz
Post 13 Jan 2014, 11:35
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1256
Location: In a West End town
sid123 wrote:
Nice, I guess we've had enough nerdy stuff, seriously something cool

Well, the last game examples by m3ntal and tthsqe raise the bar a lot especially for poor coders like myself Razz

m3ntal it looks very cool, let alone the fact that it is written with the library-language you created. I say 'it looks', for some reason i don't know i'm getting a black screen.
Post 18 Jan 2014, 08:07
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
Picnic: You're one of the reasons I come here. Me, you and tthsqe have different styles that are complimentary and not in opposition. We have our strengths and we can learn from each other. Once you have a good language+library, it's easy to make small games+programs in 1-3 days.

Black screen? Sad Question Idea Anyone else have this problem? Tested on 3 PCs with Win7. Screen BPP must be 32 (not 16), that would cause it.

https://www.youtube.com/watch?v=0FJcDBSK53o
Post 18 Jan 2014, 13:37
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 720
It has worked for me on every machine so far. Of course, there the slight bug that MHajduk mentioned.
Post 19 Jan 2014, 00:55
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
tthsqe: Good.
Quote:
slight bug that MHajduk mentioned
I was aware of this when I released it (can.move/x when jumping), but do not think it's a serious issue.
Post 19 Jan 2014, 02:30
View user's profile Send private message Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 340
Location: Asia, Singapore
Wow, the source code is so awesome, that I feel I am not seeing an assembly example but a game written in powerful HLL, which is implemented through FASM Macros,
I had a similar idea of using macros to implement sort of, class-based language using macros.
Great Work! Very Happy
Just posted this under Important/Interesting Threads.
Post 19 Jan 2014, 05:10
View user's profile Send private message Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
sid123: Thanks. Check this out: Z Language Manual (Unfinished).

PS: Please don't take it personal if I don't respond. I've been busy lately and haven't had much time to do programming. (Money is always the problem! See, if I had a minimal income - say $250 a week, what a McDonalds employee makes - I could afford to do programming everyday and I'd have more to give, but I'm po, meaning, way below "poor", constantly living in fear of being homeless again. In this world, one can have 1,000s of talents and never get paid).
Post 04 Feb 2014, 21:06
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2018, Tomasz Grysztar.

Powered by rwasa.