Author Topic: Standard RPG Game  (Read 14083 times)

0 Members and 1 Guest are viewing this topic.

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Standard RPG Game
« on: September 03, 2016, 08:35:39 pm »
Alright, so I've been working on what I would consider to be a standard RPG game. I'm using Zelda Links Awakening graphics, cause I'm not the most creative! lol. I'm more into learning how to structure a game and programming techniques. It's been fun so far! I've been using Axe as the programming language.
I'm gonna be fairly open about how I program different things, and I'll be asking for a lot of help. I'll try to keep screenshots on it, cause people like to see what's going on. Who knows, maybe I'll get it to a point that I can consider it finished!

I got some help from Sorunome on how to draw a tilemap to the back buffer and copy it to the front buffer...he's a brilliant guy. When I move the map, i shift the back buffer using the horizontal and vertical commands.  I've been able to get a masked sprite drawn on the front buffer. I do this by copying the back buffer to the front, and then masking the sprites onto the front buffer.  That's the first screenshot.

The Link sprite has his data arranged as Data("X coordinate","Y Coordinate","Direction","State")

The Directional multiplier in the third slot helps make Link's sprite face the correct direction. Basically when I press the directional keypad, it stores the numbers 1 - 4 into the third slot. When I call for Link to be drawn, the sprite pointer is offset to the correct directional sprite...if that makes sense. You can see that in screenshot 2...and don't worry about the random background map

In screenshot 3 I was able to get Link to alternate between states: standing and stepping. It's just another multiplier, just like the direction slot. I have a little routine that helps alternate between the two when moving, and resets to stand when Link's not moving.

Screenshot 4 is my little test arena for collision. I rearranged the tilemap so the fences are in different configurations for Link to approach. I feel like the collision is super basic. Depending on which direction Link goes, I check the type of tile Link would move into. If the tile is less than a certain number, its a walking tile, and Link can walk freely. If it is above a certain number, it wont let Link pass forward. I hope this explanation isn't too vague...

So, the next thing's I have in mind are;
animated tiles (like the moving flowers tile) - I'll need help on brainstorming
Link swinging sword animation
Health bar

...just one step at a time, i guess. What do ya'll think?
« Last Edit: September 03, 2016, 09:35:59 pm by Eeems »

Offline Eeems

  • Mr. Dictator
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6265
  • Rating: +318/-36
  • little oof
    • View Profile
    • Eeems
Re: Standard RPG Game
« Reply #1 on: September 03, 2016, 08:52:34 pm »
Hey @coops just an FYI, you can actually attach multiple attachments to one post (Specifically the first post). Please do that instead of posting a new post per attachment.

That said, this is looking pretty cool keep it up :)
/e

Offline TIfanx1999

  • ಠ_ಠ ( ͡° ͜ʖ ͡°)
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 6173
  • Rating: +191/-9
    • View Profile
Re: Standard RPG Game
« Reply #2 on: September 03, 2016, 09:38:24 pm »
Looking good so far!  :thumbsup:

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Standard RPG Game
« Reply #3 on: September 04, 2016, 03:19:27 am »
This is looking great so far!
Making Link a state-machine sounds like a pretty good idea to get this working :)

However, for the colision detectioin, while the link sprite is 16x16 pixels (i think) the colision is actually more like 14x10 pixels, meaning he could walk more up on a fence, the head would overlap with the fence. (not sure if the exact numbers are correct)

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Re: Standard RPG Game
« Reply #4 on: September 16, 2016, 12:41:52 pm »
I've been working on this the last little bit...sorry, no screenshots quite yet. But some quick questions.

I'm wanting to make my drawing routine for Link more general for all 16x16 bit masked objects, like enemies, npc's, etc. 
It'd be called: DrawChar(GDB0Character,Pic0Pointer). However, it doesnt seem to like me sending pointers to the routine...

DrawChar would look like this:

Code: [Select]
Lbl DrawChar
  sub(Maskʳ,{r₁},{1+r₁},256*{3+r₁}+({2+r₁}*64)+r₂)
Return

And Mask would look like this:

Code: [Select]
Lbl Mask
  Pt-Mask(r₁,r₂,r₃)ʳ
  Ptq-Mask(r₁+8,r₂,r₃+16)ʳ
  Pt-Mask(r₁+8,r₂+8,r₃+32)ʳ
  Pt-Mask(r₁,r₂+8,r₃+48)ʳ
Return

I have a feeling that it's confusing the r1, r2, etc between the two routines. Or, maybe I'm not referencing the pointers right, idk. Any thoughts?

Also, any idea on how to do animated tiles? I'm thinking of doing an interrupt routine that first checks for visible animated tiles on screen. If if finds one, it draws over it with the appropriate tile...idk..I've never done interrupts before..

Offline E37

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 358
  • Rating: +23/-0
  • Trial and error is the best teacher
    • View Profile
Re: Standard RPG Game
« Reply #5 on: September 16, 2016, 01:40:04 pm »
I don't think you need the ^r after the Mask in DrawChar.
(I think) that evaluates all of the arguments first and then saves them to r1-6.
You shouldn't need the curly braces around r1 in the first subroutine unless {GBD0} is the pointer to the sprite.
If GBD0 is the pointer to the sprite, there shouldn't need to be any curly braces.
I'm still around... kind of.

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Standard RPG Game
« Reply #6 on: September 16, 2016, 04:19:14 pm »
Could you please provide an example usage of DrawChar, including the data the pointers you pass it point to?

As to animated tiles, there is no need for an interrupt!
The basic idea is that you re-draw the entire tilemap every single frame (that would make the code you wrote for scrolling obsolete (believe me, the calc is powerful enough to easily handle that)) and have a frame counter, and then change for the animated tiles every like 8 frames the pointer of where the sprite data lies, resulting it a different frame being drawn.

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Re: Standard RPG Game
« Reply #7 on: September 16, 2016, 06:51:49 pm »
Quote
As to animated tiles, there is no need for an interrupt!
The basic idea is that you re-draw the entire tilemap every single frame (that would make the code you wrote for scrolling obsolete (believe me, the calc is powerful enough to easily handle that)) and have a frame counter, and then change for the animated tiles every like 8 frames the pointer of where the sprite data lies, resulting it a different frame being drawn.

Ya, I was thinking of a frame counter too...It should be direct enough of a process, I think.

I should have been more specific about the DrawChar subroutine. It should receive 2 pointers:

GDB0_____ - points to properties of the character: X, Y, Direction, State
Ex:
Data(20, 40, 1, 0)->GDB0


Pic0_____ - points to the actual picture of the character
Ex:
[FFAA01039... ]

Calling it would look like this
DrawChar(GDB0, Pic0)

I think it's probably the ^^r that's in the wrong spot. Or maybe the curly brackets, I'm not sure when they are used...I'll see what I can do!
« Last Edit: September 16, 2016, 06:55:52 pm by coops »

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Standard RPG Game
« Reply #8 on: September 17, 2016, 05:35:59 pm »
This is currently looking correct to me, could you please give us screenshot examples of your sprite routines? (And, if possible, a thing of how the sprite should look like)

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Re: Standard RPG Game
« Reply #9 on: September 18, 2016, 09:13:26 pm »
Yeah, I've been working on it today, and haven't had much success getting it to work...

Here's the  main loop, with Link's stats.
Code: [Select]
//Link's Character Data: X, Y, Direction, State
Data(40,24,1,0,0)→GDB1

Lbl Main
Repeat getKey(15)
  //Check if Arrow buttons or attack buttons are pressed
  ActionKey()
  //Draws Link & other masked objects to front buffer
  DrawObj()
  DispGraph
End
Return

Here's the routine that goes through drawing masked sprites; Draw Object. Pic1Link is a pointer to Link's sprite data.
Code: [Select]
Lbl DrawObj
Copy(L₃)

//Calling this should draw Link
DrawChar(GDB1,Pic1Link)

//Here's the Old Code that Only Draws Link's Sprite
//DrawLnk({GDB1},{1+GDB1},{2+GDB1},{3+GDB1})
Return

Heres a comparison of the old and new routines, and the Masking routine. The DrawChar should work the same as DrawLnk...DrawLnk works just fine.
Code: [Select]
Lbl DrawChar
  Mask({r₁},{1+r₁},256*{3+r₁}+({2+r₁}-1*64)+r₂)
Return

Lbl DrawLnk
  Mask(r₁,r₂,256*r₄+(r₃-1*64)+Pic1Link)
Return

Lbl Mask
Pt-Mask(r₁,r₂,r₃)ʳ
Pt-Mask(r₁+8,r₂,r₃+16)ʳ
Pt-Mask(r₁+8,r₂+8,r₃+32)ʳ
Pt-Mask(r₁,r₂+8,r₃+48)ʳ
Return

When I use DrawChar I get a scrambled sprite in a random location...interestingly enough, the collision works despite the sprite not being in the right spot...Any ideas?

Offline Runer112

  • Moderator
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Standard RPG Game
« Reply #10 on: September 18, 2016, 10:15:07 pm »
This is because of Axe's weirdness of all functions sharing the same argument variables, r1-r6. Often you can fix the problem by using the "recursive" syntax that you initially tried using, but that turns out not to even help in this case. That's because argument values are saved to their respective variables immediately after they're evaluated, making code like this:

Code: [Select]
Lbl DrawChar
  Mask({r₁},{1+r₁},256*{3+r₁}+({2+r₁}-1*64)+r₂)
Return

Really act like this:

Code: [Select]
Lbl DrawChar
  {r₁}→r₁
  {1+r₁}→r₂
  256*{3+r₁}+({2+r₁}-1*64)+r₂→r₃
  Mask()
Return

As you can see, r₁ is overwritten after evaulating the first argument and r₂ is overwritten after evaluating the second argument to the Mask() call, resulting in their uses in the second and third arguments producing bad values.

Although it's rather annoying/silly, a simple way to fix this is to assign the argument variables manually like demonstrated in the code block above, but in the reverse order, so none are overwritten before their old values are done being referenced (if there were cyclical dependencies, you'd have to introduce temporary stores as well):

Code: [Select]
Lbl DrawChar
  256*{3+r₁}+({2+r₁}-1*64)+r₂→r₃
  {1+r₁}→r₂
  {r₁}→r₁
  Mask()
Return

Also, because Axe is really dumb and doesn't (yet) know about the commutative properties of mathematical operators and how to optimize by switching operand order, I would recommend that you get in the habit of doing this yourself. It is almost always best to make constants the second operand, or if neither operand is a constant, try to make a simple variable the second operand. Here's the fixed code from above with this optimization applied in a couple places:

Code: [Select]
Lbl DrawChar
  {r₁+3}*256+({r₁+2}-1*64)+r₂→r₃
  {r₁+1}→r₂
  {r₁}→r₁
  Mask()
Return

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Re: Standard RPG Game
« Reply #11 on: September 19, 2016, 03:33:11 pm »
Thanks Runer112! It was exactly what I needed! I'm still new to the whole Axe language, so a lot of the little details I need to grasp.

I've worked on the animated tiles bit. I've made it where a timer increments. Every 50 frames a routine is called to draw over the animated tile spots with the appropriate tile. Some limitations though are all animations must be 4 frames and I have to code in each new animated tile. I could make it more robust, but I think the point is to have something moving on screen so the player knows the calc hasn't frozen :P

I think my next step is I'm going to incorporate bushes. I was going to put them in as a separate object from the map, but now thinking about it, it's probably best to have them part of the tilemap. When a bush is 'cut', I replace the bush tile with a ground tile, and I send an animation of leaves moving over the bush...this will take a while cause I also have to include Link's sword animations and some sort of sword collision...yeah...

Nevertheless, Link's got himself a beach house. His flower garden waves around in the breeze, and the ocean waves are moving gently. :D

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Standard RPG Game
« Reply #12 on: September 19, 2016, 03:34:33 pm »
To not requiring every tile to be a 4-frame animation you could maybe make that only tiles above a certain ID are animated, below they are static

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!

Offline coops

  • LV3 Member (Next: 100)
  • ***
  • Posts: 58
  • Rating: +3/-0
    • View Profile
Re: Standard RPG Game
« Reply #13 on: September 19, 2016, 03:43:47 pm »
Quote
To not requiring every tile to be a 4-frame animation you could maybe make that only tiles above a certain ID are animated, below they are static

yeah, I'm already using that for collision...I have it set up where any tile with an ID below 10 is a walkable tile. Above 10 is an unwalkable one...

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Standard RPG Game
« Reply #14 on: September 19, 2016, 03:45:05 pm »
You can have it like this then:
(for example)
0-7 : walkable, static
8-10 : walkable, animated
11-42 : wall, static
43-99 : wall, animated

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!