Omnimaga: The Coders Of Tomorrow
Welcome, Guest. Please login or register.
 
Omnimaga: The Coders Of Tomorrow
23 May, 2013, 00:13:03 *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   home   news downloads projects tutorials misc forums rules new posts irc about Login Register  
+-OmnomIRC

You must Register, be logged in and have at least 40 posts to use this shout-box! If it still doesn't show up afterward, it might be that OmnomIRC is disabled for your group or under maintenance.

Note: You can also use an IRC client like mIRC, X-Chat or Mibbit to connect to an EFnet server and #omnimaga.

Pages: [1] 2 3   Go Down
  Print  
Author Topic: Arrays in Axe (Enemy/Bullet Code Tutorial) -  (Read 2723 times) Bookmark and Share
0 Members and 1 Guest are viewing this topic.
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« on: 20 February, 2011, 20:40:14 »
+5

This is going to be a monster tutorial that'll take a while for me to write, so here are the first five parts:

Arrays and Bullet Code

Axe doesn't natively support any data structures, but that doesn't mean you can't use any in your Axe programs. Because Axe allows you to manipulate the bytes and bits of your calculator all you want, you can make your structures, made in whatever way best suits you. Axe is a versatile tool.

One of the most useful data structures (by far) is the array. An array is just a list of data elements, which could be anything—bullets, enemies, lobsters, etc. In fact, if you think about it, a tilemap is a type of array (a two-dimensional one).

So how do you make an array in Axe? Well, first you need to decide where to put it. Any safe RAM area (L1, L2, etc.) will do. Just make sure it's reasonably big enough. Arrays can take a lot of memory.

Now decide how each element is going to be stored. What are you representing with each element? Just for the sake of example, let's say you're making a program to keep track of some squares floating around the screen but always going in one direction. You'd need to keep track of its X and Y values, as well as how fast it's moving horizontally and vertically. That would be four bytes per element. (You could probably cut it down to three or even two if you desparately neede to, but I'll keep things simple.) The array could look like this:



Like with everything in Axe, we start counting from 0 because it makes our lives much, much easier.

To start working on our example, make a program called ASQUARE as follows:





This will be our main program. It should be pretty simple to understand: it first initializes some data (the code for which we're going ot put in a subprogram called ASQUI), then goes in a loop where it draws the squares until you quit. prgmASQUR will hold our subroutines.

For program ASQUI, just put this in:



That's it. L will hold the current size (length, number of elements) of the array. It'll get updated whenever we modify the array (in the subroutine itself).

Displaying objects in the array

An array of data (or any other data structure) is pretty much useless unless you do something with it. Here we'll make the subroutine DA that displays all the elements in the array.

First, make a new program called ASQUR and put this inside. All our routines will go in it.



Quote from: Draw all elements
Variables:
    The only global variable you really need will be one giving you the size (length) of the array (L).
    
    L - current length of array (initialized to 0 at the beginning of the program and updated by the routine itself)

Input:
    None.

Output:
    None. It draws the sprites to the buffer, but that's pretty much it.

Code:


You probably don't need too much explaining, so I'll keep it short. First, there's "If L." This is to avoid an (almost) infinite loop when L happens to be zero. (We loop from 1 to L and subtract four more instead of from L-1 to L-1 because it's a lot faster to check each pass of the loop.) Then the routine loops through every element, using Pt-Change( to display each one.

We use Pt-Change( here because it's the easiest to work with when you want to draw a moving object. It works like this: Just before the main program calls DispGraph, we draw all the squares onto the screen so they appear, and once the screen finishes displaying, all the squares get removed with the same routine to make it "clean" again. This makes things easier if you're making a complex tilemap game where redrawing the entire screen every frame takes too much time.

Anyway, now that you've defined the subroutine, you can compile your program now! And run it! what does it do?

Nothing. It waits until you press CLEAR. That's because you haven't added any elements to the array yet. We'll get there in the next step.

Manipulating the array

Now a routine to add (push) an element to the end of the array. Put this in program ASQUR.

Quote from: Pushing an element
Variables:
    The only global variable you really need will be one giving you the size (length) of the array. Let's call it L.
    
    L - current length of array (initialized to 0 at the beginning of the program and updated by the routine itself)

Input:
    Since each element holds four values, let's make each one an argument.
    
    r1 - X-value of new square
    r2 - Y-value of new square
    r3 - X-speed of new square
    r4 - Y-speed of new square

Output:
    None. (Of course, you could easily modify it to return a useful value, such as a pointer to the element added.)

Code:


Scary? Fine, I'll break it down.

Before it does anything, it checks if there are 177 elements in the list. This is because L1 can only hold 714 bytes of data, which is approximately 178*4 elements. If you're using any safe RAM location, make sure you change this limit accordingly. Having too many elements is called an overflow, which could mess up whatever data comes after L1 (in this case the variables A through T.

First look at the very inside of the mess of braces, at the line "L+1?L*4+L1-4." The real action starts there. First, it increments L by one (you probably know why). Since that command returns the value of L, you can keep doing operations on it (multiplying by four in this case). Since each element in our example is four bytes long, L*4 gets the offset of the next element in the array. But there's a problem here: Since you incremented L already, this now points four bytes ahead of where you're supposed to be. We take care of this by adding only L1-4 to the total.

That gives us a pointer to where to store the first byte of the element, so "r1?{L+1?L*4+L1-4}" would store the first byte there.

Now here's the fun part: By storing to a variable location, the pointer you stored to is returned in HL. That means that you can keep on storing to the byte after it by simply adding one! That's why the line above is enclosed by "r2?{ ... +1}": you just add one to get the next byte, then store to it. You can keep going like this for as long as you want; it's the single most optimized way to store a mass of variable data in Axe!

Next up we'll actually add the pretty squares. Promise.

Actually doing something

Finally we're going to add the actual enemies (squares). Here are some ideas for how they should be added:

  • Enemies always start at the center of the screen. That would be (44, 28).
  • Enemies should move in a random direction.
  • Enemies spawn at random times.

To do this, we need to back to the main program, into the main loop (Repeat getKey(15):End). Change prgmASQUARES into this:





All the changes come just before the first sub(DA).

You probably understand this too. If a random two-byte integer is less than 4096 (that's a chance of 4096/65536, or 1/16), stick a square in the middle of the screen and give it a random X- and Y-speed. Then quit when the user presses CLEAR.

Before we compile, there's one thing that's missing. Something that every enemy/bullet system needs to have—movement. So change prgmASQUARES again:







All the new additions are right after the ones you just added. The point here is that it has to be before the first sub(DA). Otherwise, you'd be changing the squares' position after they get drawn but before they get erased, so they'd end up being "erased" from a different location.

Well? Compile and run!



It works! Amazing, eh? You can let it run for as long as you want, and even though it slows down quite a bit with a lot of enemies on the screen, they all move on their own!

The only problem now is that they keep wrapping around the screen. Usually that's not what you want to happen, since if an enemy or bullet goes off the screen, it should stay off the screen. We'll take care of that in the next section.

Getting rid of the extras

To make the squares more realistic enemies, we're going to remove them when they go off the screen. That calls for a new routine:

Quote from: Removing an element
Variables:
    And yet again, you need L.
    
    L - current length of array (initialized to 0 at the beginning of the program and updated by the routine itself)

Input:
    Well, we need to know which element ot remove.
    
    r1 - Index of element to remove

Output:
    None. (Again, you can modify it to return something useful, but we won't here.)

Code:


You can probably tell that it's a copy statement. What we're trying to do is copy everything after the element to be removed four bytes back—overwriting the element you want to remove. The routine also takes care of the array length variable (L) by subtracting one.

The only thing that should seem weird here is the extra "+1" at the end. It might not make sense, but it takes care of the case where you're trying to remove the very last element. If that extra little bit of code weren't there, the Copy( statement would try to copy 0 bytes backwards, which gets translated to a copy a 65536 bytes, which is definitely not what you want. This extra bit doesn't do us any harm besides slowing the program down a tiny, tiny bit, but it takes care of that scenario for us.

So now that you have the routine down, let's actually use it. Go back into the main program and change it to this:









All the changes are in the For(I,1,L) loop. It basically tests the X- and Y-values after they're changed to see if they're completely off the screen, and if so, they get removed. The reason I jump to a lable RM instead of writing the code twice is because it's smaller and even gets rid of any chance of some certain nasty coincidences I won't talk about here. The point is it works.



Arrays in arrays (in arrays)

So there you are. Arrays in Axe.

Before we leave you to coding in peace, there's one last trick we're here to teach you: how to make arrays whose elements are arrays in their own right, or arrays of arrays.

Arrays in arrays? What's the point of that?

Surprisingly, you can do a lot with them. For example, say you have a puzzle game where each level has a fixed set of enemies. Instead of making a gigantic if-elseif-elseif-elseif... structure, you can put the enemy data for each level in an array, then organize that whole thing into an array.

But here's the problem: How do you store an array of elements that aren't a fixed size? The real problem comes in parsing it—how could you loop through a list whose elements could be any number of bytes long?

Like with any varying array, the solution comes in embracing the pointers. By that we mean simply that you don't have to put the structures themselves into the array; just point to them. Here's an example.

First, create the raw data you're going to put into an array.



Here are the first-level arrays:



Notice we use Data( with each pointer followed by an r (since pointers are always two bytes). The 3 and 2 in the beginning denote the number of elements in that array, since this value can change. Now it's the arrays' turn to be referenced from an array, in much the same way:



The increments are there to offset the length prefixes on those arrays.

To do something with this, let's loop through the array and all its arrays to print whatever is stored there:



With that, let's call it a day. Enjoy your newfound powers and happy coding!

[img]http://clrhome.org/
« Last Edit: 20 April, 2012, 00:44:29 by Deep Thought » Logged




Happybobjr
James Oldiges
LV11 Super Veteran (Next: 3000)
***********
Offline Offline

Gender: Male
Last Login: Yesterday at 22:35:58
Date Registered: 01 June, 2010, 00:52:05
Location: IN, United States
Posts: 2273


Total Post Ratings: +100

View Profile
« Reply #1 on: 20 February, 2011, 20:44:10 »
0

How do you deal with speed in axe, I have never gotten that Undecided
« Last Edit: 20 February, 2011, 23:41:40 by Deep Thought » Logged

School: East Central High School

Axe: 1.0.0
TI-84 +SE  ||| OS: 2.53 MP (patched) ||| Version: "M"
TI-Nspire    |||  Non-Cas |||  OS: 1.1 |||  Build: Old  |||  84+ keypad.   Being lent out
____________________________________________________________
Munchor
LV13 Extreme Addict (Next: 9001)
*************
Offline Offline

Gender: Male
Last Login: 21 May, 2013, 17:58:01
Date Registered: 16 October, 2010, 15:39:13
Location: Position
Posts: 6209


Total Post Ratings: +174

View Profile
« Reply #2 on: 20 February, 2011, 20:45:44 »
0

How do you deal with speed in axe, I have never gotten that Undecided

Speed like of the processor (MHz?)
« Last Edit: 20 February, 2011, 23:41:46 by Deep Thought » Logged
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #3 on: 20 February, 2011, 20:46:17 »
+1

How do you deal with speed in axe, I have never gotten that Undecided

When you move an object, just add more to its X/Y values to make it go faster.

And part 2 has been added! This'll be the last part for today.
« Last Edit: 20 February, 2011, 23:41:52 by Deep Thought » Logged




leafy
Coder Of Tomorrow
LV10 31337 u53r (Next: 2000)
*
Offline Offline

Gender: Male
Last Login: 20 May, 2013, 21:59:01
Date Registered: 26 December, 2010, 05:27:03
Location: the ninth circle of hell
Posts: 1545


Total Post Ratings: +371

View Profile WWW
« Reply #4 on: 20 February, 2011, 20:46:31 »
0

Yay, Ive always wondered how to remove a certain object from an array.
Logged

In-progress: Blastlabs, TMJO, qb?, VVVVVV?
Finished: Tag, Tap, MFQT, Nyan
Dead: Graviter
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #5 on: 20 February, 2011, 20:48:18 »
0

Yay, Ive always wondered how to remove a certain object from an array.

Sorry, that's planned for part 5 or 6, so it'll take a while.

Next will be how to let the objects move around the screen.
Logged




Munchor
LV13 Extreme Addict (Next: 9001)
*************
Offline Offline

Gender: Male
Last Login: 21 May, 2013, 17:58:01
Date Registered: 16 October, 2010, 15:39:13
Location: Position
Posts: 6209


Total Post Ratings: +174

View Profile
« Reply #6 on: 20 February, 2011, 20:48:57 »
0

Speed:


1
2
3
4
5
6
7
8
9
Repeat getKey(15)
Pt-On(X,Y,Pic1
If getKey(1)
Y+1->Y
.Just change the 1 above to raise speed.
End
DispGraph
End
Logged
FinaleTI
Believe in the pony that believes in you!
Coder Of Tomorrow
LV10 31337 u53r (Next: 2000)
*
Offline Offline

Gender: Male
Last Login: 03 May, 2013, 16:35:01
Date Registered: 04 June, 2010, 00:34:27
Location: Alteria
Posts: 1818


Total Post Ratings: +118

View Profile WWW
« Reply #7 on: 20 February, 2011, 21:02:08 »
0



Looks good, but aren't labels only supposed to be up to 3 chars?
« Last Edit: 20 February, 2011, 21:04:09 by FinaleTI » Logged





So, yeah, I have a blog now. Nothing special, just your average ghost town.

Spoiler for Projects:
Spoiler for Pokemon TI:
Map engine is going to be redone from scratch, since I was lacking in organization last time. With a project as big as Pokemon, planning and organization is key, so that will probably be the brunt of the work done on this project for the time being.

Spoiler for Nostalgia:
Being worked on. Nothing really new to put here, but it's being worked on.

Spoiler for Finale's Super Insane Tunnel Pack of Doom:
I will be combining Blur and Collision Course into a single gamepack.

Spoiler for Nostalgia Origins: Sky's Story:
Currently on hold. I am unsure of whether this will remain DCS7 Hybrid BASIC or if it will use Batlib, Grammer or perhaps Axe.
This may see more progress once a demo of Nostalgia is released.
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #8 on: 20 February, 2011, 21:03:06 »
0

Dang, I've always used 2, so I didn't know what the limit was...

EDIT: Fixed.

EDIT2: Finished the first example program! Next I'll be explaining how to get rid of the enemy when it goes off the screen and how to make it shoot bullets Cheesy

EDIT3: You know it's long when a post takes up half the page O.o
« Last Edit: 22 February, 2011, 04:40:25 by Deep Thought » Logged




Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #9 on: 22 February, 2011, 04:41:12 »
0

Added another section!

Yay, Ive always wondered how to remove a certain object from an array.

Well finally I've added it Smiley Look under "Getting rid of the extras."
Logged




ztrumpet
The Rarely Active One
LV13 Extreme Addict (Next: 9001)
*************
Offline Offline

Gender: Male
Last Login: Yesterday at 03:10:30
Date Registered: 08 November, 2009, 21:10:12
Location: Michigan
Posts: 5687


Total Post Ratings: +360

View Profile
« Reply #10 on: 22 February, 2011, 04:58:57 »
0

I love how it is so far.  Great job Deep!
Logged

leafy
Coder Of Tomorrow
LV10 31337 u53r (Next: 2000)
*
Offline Offline

Gender: Male
Last Login: 20 May, 2013, 21:59:01
Date Registered: 26 December, 2010, 05:27:03
Location: the ninth circle of hell
Posts: 1545


Total Post Ratings: +371

View Profile WWW
« Reply #11 on: 22 February, 2011, 05:15:21 »
0

Ooohhh, you use the Copy( and pointer before...ahhh, that's genius.
Logged

In-progress: Blastlabs, TMJO, qb?, VVVVVV?
Finished: Tag, Tap, MFQT, Nyan
Dead: Graviter
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #12 on: 22 February, 2011, 05:23:35 »
0

And what's great is that you can easily change it a bit to remove elements of any size, and even remove multiple elements at once (for example if two objects are always tied to each other). There are even ways to make arrays of different-sized elements Cheesy A bit hard to keep at a decent speed, but really fun to work with.
Logged




DJ Omnimaga
Retired Omnimaga founder (Site issues must be PM'ed to Netham45, Eeems, Shmibs, Deep Thought and AngelFish, not me.)
Editor
LV15 Omnimagician (Next: --)
*
Online Online

Gender: Male
Last Login: Today at 00:10:23
Date Registered: 25 August, 2008, 07:00:21
Location: Québec (Canada)
Posts: 50221


Total Post Ratings: +2615

View Profile WWW
« Reply #13 on: 22 February, 2011, 06:53:50 »
0

Nice Deep! Some people wondered how to have games like shoot-em-ups before and were unsure because they didn't knew how to deal with arrays. Should be pretty useful!
Logged

Retired 83+ coder, Omnimaga/TIMGUL founder. Now doing power metal music (formerly did electronica)

Follow me on Bandcamp|Facebook|Reverbnation|Youtube|Twitter|Myspace
Deep Thought
So much to do, so much time, so little motivation
Administrator
LV13 Extreme Addict (Next: 9001)
*
Offline Offline

Gender: Male
Last Login: 19 May, 2013, 19:18:47
Date Registered: 19 May, 2009, 08:00:00
Location: The Universe
Posts: 7813


Topic starter
Total Post Ratings: +706

View Profile WWW
« Reply #14 on: 22 February, 2011, 07:06:01 »
0

Nice Deep! Some people wondered how to have games like shoot-em-ups before and were unsure because they didn't knew how to deal with arrays. Should be pretty useful!

I think someday I'll convert this to a shoot-em-up tutorial that'll guide you through the entire process Cheesy This is pretty close, anyway.
Logged




Pages: [1] 2 3   Go Up
  Print  
 
Jump to:  

Powered by EzPortal
Powered by MySQL Powered by SMF 1.1.18 | SMF © 2013, Simple Machines Powered by PHP
Page created in 0.418 seconds with 31 queries.
Skin by DJ Omnimaga edited from SMF default theme with the help of tr1p1ea.
All programs, games and songs avaliable on this website are property of their respective owners.
Best viewed in Opera, Firefox, Chrome and Safari with a resolution of 1024x768 or above.