Hey, I'm trying to make a 2D maze game in Axe with ASCII symbols (so I can eventually turn it into a roguelike).

I started it in Ti-BASIC. Here's the BASIC code:


Code:
ClrHome
1->X
1->Y
Menu("The Maze Game","Start",ST,"Quit",QT
Lbl ST
While 1
Repeat getKey
getKey->K
If K=25 and Y!=0:Then
Y-1->Y
Goto DP
End
If K=34 and Y!=60
Then
Y+1->Y
Goto DP
End
If K=24 and X!=0:Then
X-1->X
Goto DP
End
If K=26 and X!=60
Then
X+1->X
Goto DP
End
Lbl DP
ClrDraw
Text(Y,X,"A"
DispGraph
Goto ST


But this version doesn't work well at all.
Then I decided to do this in Axe so I could do more things with the game (and so it would be much faster). Here's my attempt at porting the code above:


Code:
.MAZEGAME
3C409EA2A29E423C->Pic1
DiagnosticOff
ClrHome
1->X
1->Y
Lbl ST
Repeat getKey(15)
If getKey(1) and (Y!=0)
Y-1->Y
sub(DP)
Else
Goto ST
End
If getKey(2) and (Y!=60)
Y+1->Y
sub(DP)
Else
Goto ST
End
If getKey(3) and (X!=0)
X-1->X
sub(DP)
Else
Goto ST
End
If getKey(4) and (X!=60)
X+1->X
sub(DP)
Else
Goto ST
End
Lbl DP
ClrDraw
Pt-On(X,Y,Pic1)
DispGraph
Goto ST
End


But this doesn't work at ALL. All I see is a blank screen, and when I press [CLEAR] it exits.

Can I have some help please?

Edit by Merth: Added code tags around your code. In the future please be sure to add them.
Your sprite needs to be in square brackets for it to show up.
Today, I printed out the Axe commands list and changed up the axe version a bit.
Here's what I came up with:


Code:
.MAZEGAME
DiagnosticOff
[3C409EA2A29E423C]->Pic1
ClrHome
0->X
0->Y
sub(DP)
Lbl ST
getKey
If getKey(4) and (Y!=0):Y-1->Y:sub(DP)
ElseIf getKey(1) and (Y!=56):Y+1->Y:sub(DP)
ElseIf getKey(2) and (X!=0):X-1->X:sub(DP)
ElseIf getKey(3) and (X!=88):X+1->X:sub(DP)
ElseIf getKey(15):Return^^r
End
Lbl DP
ClrDraw
Pt-On(X,Y,Pic1)
DispGraph
Goto ST


Sometimes when I press [CLEAR] to exit the game, the calc crashes or maybe it shows the DCS7 Help window or just shows a blank screen but its still on or something. It doesn't happen every time, but is this a bug in the game? I compiled it using Axe 1.1.2 and compiled it for the Axe Fusion option.
I'm taking another look at your code, and I will just be completely honest: it's just horrendous. Here's a rewritten version of your same code with all of those issues fixed, complete with comments (preceded by periods as per Axe syntax):

Code:
.MAZEGAME
DiagnosticOff
[3C409EA2A29E423C]->Pic1
ClrHome
0->X
0->Y
.sub(DP) was removed - you don't need it
.Lbl-Goto is highly frowned upon unless you're using it to break out of a For loop. Additionally, getKey and getKey() are two completely different methods: the former uses the TIOS to read the last key pressed, but getKey() is a custom method that checks for the particular keycode you supply, and returns 1 if it's pressed and 0 otherwise. Thus, this "Repeat until Clear is pressed" loop around your main code works far, far better.
Repeat getKey(15)
.Removed getKey. Again, getKey and getKey() are completely different, and you don't need both.
.In Axe, the ? works almost exactly like "and" in a logical setting: Basically, if the condition before a ? is false, the system jumps to the end of the line.
.In addition, you don't need the sub(DP) everywhere. This was creating a very, very long call stack every time you hit a key. Your code will reach the display code just fine without a sub(DP).
.Also, I'm going to be optimistic and assume that your != is not actually an exclamation point followed by an equals sign; but I changed it to the actual ≠ sign for easier readability.
If getKey(4)?Y≠0:Y-1->Y
ElseIf getKey(1)?Y≠56:Y+1->Y
ElseIf getKey(2)?X≠0:X-1->X
ElseIf getKey(3)?X≠88:X+1->X
.Removed statement about getKey(15). You don't need to check for getKey(15) in here anymore, now that you're doing it for your master Repeat loop.
End
Lbl DP
ClrDraw
Pt-On(X,Y,Pic1)
DispGraph
.This ends the Repeat getKey(15) loop from earlier.
End
.And this gets you out of the program
Return


EDIT: Please tell me if there's any part of this fixed code that you would like clarification on. Also, if you want, I can teach you how to implement a subroutine correctly.
Wow, thanks!

I guess I need some lessons in Axe optimization...I was wondering why the executable was bigger than the source code...


I do have some questions though.

The screen will be updated after a keypress. But eventually, I'll add walls and such to make a "maze". So I'll need to make a binary map of the walls. You know, like this:


Code:

[1,1,1,1,1,1,1,1
 1,0,0,0,0,0,0,1
 1,0,0,0,0,0,0,1
 1,0,0,0,0,0,0,1
 1,0,0,0,0,0,0,1
 1,0,0,0,0,0,0,1
 1,0,0,0,0,0,0,1
 1,1,1,1,1,1,1,1]



So, don't I need the display to be a subroutine?
Not necessarily. Since it will only be called once, it can be in your main game loop. I would still have the Lbl DP there so that you can use zStart 1.3.010 to jump to that point in the code instantaneously. Basically, code warrants use of a subroutine if it is going to be called more than once, with the same or slightly different arguments.

Here's the proper form for defining a subroutine: Somewhere outside your main program logic (after the final Return that gets you out of the program), you put this code:

Code:
Lbl NAME
...some code...
Return

where NAME is the name of the subroutine you want to create. Then, anywhere else in your code (even within NAME itself), you can put sub(NAME). When execution reaches that point, it will jump to your subroutine and start running it. Once it reaches a Return, the subroutine will end, and execution will resume at the point where you left off.

EDIT: And here's the improved code with the comments removed:

Code:
.MAZEGAME 
DiagnosticOff 
[3C409EA2A29E423C]->Pic1 
ClrHome 
0->X 
0->Y
Repeat getKey(15)
If getKey(4)?Y≠0:Y-1->Y
ElseIf getKey(1)?Y≠56:Y+1->Y 
ElseIf getKey(2)?X≠0:X-1->X 
ElseIf getKey(3)?X≠88:X+1->X
End 
Lbl DP 
ClrDraw 
Pt-On(X,Y,Pic1) 
DispGraph
End 
Return
but the ?'s don't work! Here's my code now with the > and < signs:


Code:
.MAZEGAME
DiagnosticOff
[3C409EA2A29E423C]->Pic1
ClrHome
0->X
0->Y
Repeat getKey(15)
If getKey(4)?Y>0:Y-1->Y
ElseIf getKey(1)?(Y<56):Y+1->Y
ElseIf getKey(2)?(X>0):X-1->X
ElseIf getKey(3)?(X<88):X+1->X
End
Lbl DP
ClrDraw
Pt-On(X,Y,Pic1)
DispGraph
End
Return


What's still wrong?
Try putting the code that adds to X and Y on a separate line instead of followed by a colon. Axe treats colons and newlines slightly differently.

Also, instead of X+1->X, you can just say X++, as well as X-- for X-1->X. These shortened instructions are more optimized and are common tasks for a computer.
Thanks, that worked!

Now, how would I show walls? Because I want this to look a bit like DoomRL, I would like the wall tiles to be # signs.

How could I show the walls and have collision detection that is efficient and fast (and small size?)
I'd say that the cleanest way to do graphics is through the graph screen, even if you want to do text, and sprites are better than actual text characters in terms of speed, so only use text if you actually need it. You are, however, free to make your sprites look like ASCII.

As for showing walls and other terrain, you would create a tilemap, stored as a long string of HEX characters (use Pixelscape to help you do this). Once that map is defined, this line of code (in its general form):

Code:
{Y*width+X+address}

will get the tile at X,Y (given that the tilemap's width is supplied and "address" is the data pointer you gave to the tilemap). To do collision detection, you would poll the particular tile. And to draw the tiles, you would iterate through X and Y using a double nested For loop.
I've moved this topic to the general programming forum.
Wait, Compynerd255, how exactly do I do the tilemap thing?

Can you give me an example please?
GinDiamond wrote:
Wait, Compynerd255, how exactly do I do the tilemap thing?

Can you give me an example please?

I actually created a program a while ago that translates a tilemap in a matrix to an Axe tilemap that you can paste into a program: http://www.ticalc.org/archives/files/fileinfo/443/44386.html . The readme shows some examples.

Edit by Catherine: Fixed your link so it works
the link is broken

Oh, and can the tilemap thing support two types of sprites?
I want to do something like this:


Code:

################
#..............#
#..............#
#..............#
#..............#
#..............#
#..............#
################
Fixed the link for you. It just had an extra "." at the end.
Oh, and here's the current code:


Code:
.MAZEGAME
DiagnosticOff
[3C409EA2A29E423C]->Pic1
ClrHome
0->X->Y
Repeat getKey(15)
If getKey(4)?Y>0
Y--
ElseIf getKey(1)?Y<56
Y++
ElseIf getKey(2)?X>0
X--
ElseIf getKey(3)?X<88
X++
End
Lbl DP
ClrDraw
Pt-On(X,Y,Pic1)
DispGraph
End
Return


Is there a way to optimize the ClrDraw (code) DispGraph? I have a feeling that its a bit slow (or will become slow)...
GinDiamond wrote:
Is there a way to optimize the ClrDraw (code) DispGraph? I have a feeling that its a bit slow (or will become slow)...

You will want to keep your basic ClrDraw / DispGraph pattern - when you draw a lot of objects in a game, it's better to clear them all at once than to try erasing them one by one.

The strategy that works best in the general case is to use the DispGraphClrDraw command (the DispGraph token immediately followed by ClrDraw). Basically, it's like doing a DispGraph, then a ClrDraw, but the procedure is almost as fast as DispGraph alone. So, to implement this strategy:
1. Stick a ClrDraw right before your main game loop.
2. Get rid of the ClrDraw inside your main game loop.
3. Change the DispGraph in your loop to a DispGraphClrDraw.

Since your game is a roguelike and won't be actively scrolling the map, you can also try caching your rendered map into some other buffer, then instead of doing a ClrDraw, copy this other buffer into the normal buffer, thus saving you the time of rendering the map every frame. Here's how you'd implement that strategy:
1. Decide where in memory you want to put your buffer. You have three choices: L3 (if you aren't using grayscale), L1 (if you #Realloc your variables to L4 and aren't archiving/unarchiving in your program), or an Appvar (create an appvar with some random name that's 768 bytes long, then keep that pointer for the rest of the program). Before your game loop begins, clear this buffer.
2. Keep another variable, such as θ, as an "update sentry variable". Set this to 1 before the loop begins. As you go through your loop, if you do something that causes the map to change (such as going to another screen), set the update sentry variable to 1.
3. Once you've done all your update actions (anything that could possibly change the sentry variable), check the sentry variable:
- If the variable is not zero, clear both the graph buffer and the other buffer. Draw your map on the graph buffer, then copy the graph buffer to the other buffer.
- Otherwise, simply copy the other buffer to the graph buffer. The other buffer contains your map, which is 100% accurate since your map has not changed (indicated by your sentry variable being 1). In addition, anything that was on your graph buffer is cleared by this operation.
4. In either case, set your sentry variable to zero, draw all your volatile stuff (such as the player and monsters), and DispGraph.

Obviously, you can't use both of these strategies at the same time, since it would be pointless. I implement a similar strategy in my Eitrix game to cache the block grid.
Thanks!

See, I want my roguelike to be like a classic ASCII/terminal roguelike, sort of like DoomRL

Do I make a binary 8x16 matrix and use that for collision detection? How can I display a # sign at each 1 on the matrix and a . at each 0?
how do I do a tilemap? The most I can get is repeated tiles all over the screen.
Okay, I figured out how to do a tilemap. Here's the picture:



Now, do I export it as an Axe program, an appvar, or picture (for calc)?
How would I use it?
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
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

 

Advertisement