Well, I wasn't planning on making a post this early into the project, but SAX has encouraged me to show my code (mainly to prove my bad code works). I've been trying to learn C lately; so, like any normal person, I gave myself the unrealistic goal of creating an entire Jetpack Joyride port for a calculator and then seeing how many features I could pack in while making it extremely efficient.

So far I've got:
-Terrible background drawing function (to be replaced today or tonight)
-Controls for avatar, Barry Steakfries
-Barry sprite and simple running animation
-Coin sprites and hitbox calculations
-Coin counter
-Black boxes O' death that will be the obstacles once I've finished getting the sprites made
-FPS limiting to 25 and a counter to show what the true FPS would be if it weren't locked (for debugging really)

What needs to be done:
1. Obstacles and sprites
-Get zapper and zapper-beam hitboxes set up
*make sprites
-make missiles and hitbox calculations
*make sprites
*make little warning icons
*find an efficient way to create smoke trail effect

2. Make Barry die
-animations for death by zapper
-animations for death by missile
-bounce corpse around after death
-make a "health" system where shields add 1-5 points depending on upgrades

3. Powerups
-make all the powerups
*cash dash
*rocket time
*boost
*shield
**health system, shields only spawn at 1 health and can add more depending on upgrades

4. Vehicles
-all of them
-S.A.M. is considered a vehicle but I don't know if I'll have room for it later on

5. Custom graphics for characters, lab environment, and scientists
-graphics will be stored in an appvar with the defaults hard-coded as place holders
-should make a menu system to select which sprites from which appvar to use for each object

6. Make scientists that you can torment

Well, there's a lot to be done, but so far I've been chugging along making sprites as fast as I can. I've attempted to pull them from the .apk file (which is so easy I thought I was doing something wrong), but they're saved as .tex files, which appear to be encrypted or compressed in such a way that I can't open them. I've resorted to screenshotting my phone and then just pulling the sprites from there, which leaves much to be desired.

Anyway, here's the part that everyone actually came here to see that started WWIII in the SAX: gravity modeling!

Here's what I was using:

Code:
        //run controls until Barry gets wasted, then bounces his corpse around:
        if (health > 0)
        {   //controls for avatar:
            if (kb_Data[1] & kb_2nd)
            {
                if((BarryY > 5) && (holdTime < 8))
                {
                    holdTime += 1;
                }
            } else {
                if((BarryY < (185)) && (holdTime > -8))
                {
                    holdTime -= 1;
                }
            }
            //I will never admit that I forgot about the exponent key and spent 2
            //hours trying to find a cube root formula that works in C. Never.
            BarryY -= ((holdTime^(1/3)));

            //sees if Y-value rolled past zero or 198, figures out if it was going up
            //or down, and auto-corrects accordingly:
            if ((BarryY > (186)) || (BarryY < 5))
            {
                if (holdTime > 0)
                {
                    BarryY = 5;
                } else {
                    BarryY = (185);
                }
                holdTime = 0;
            }
        }

What it did:


...And here's what I wrote at 12 AM this morning after staying up playing Super Mario Sunshine like a responsible human being:

Code:
        //run controls until Barry gets wasted, then bounces his corpse around:
        if (health > 0)
        {   //controls for avatar:
            if (kb_Data[1] & kb_2nd)
            {
                if((BarryY > 5) && (holdTime < 12))
                {
                    holdTime += 1;
                }
            } else {
                if((BarryY < (185)) && (holdTime > -10))
                {
                    holdTime -= 1;
                }
            }

            //SAX got pretty mad about this, turns out this also models a curve and
            //is actually just as good:
            BarryY -= (holdTime);

            //sees if Y-value rolled past zero or 198, figures out if it was going up
            //or down, and auto-corrects accordingly:
            if ((BarryY > (186)) || (BarryY < 5))
            {
                if (holdTime > 0)
                {
                    BarryY = 5;
                } else {
                    BarryY = (185);
                }
                holdTime = 0;
            }
        }

What the final code does (the FPS and coin counter are swapped here as a design change):


They both do the same thing, which actually is confusing me a little bit now, and I see why no one thought the cube-root function would work. I actually was using a form of the second code originally for testing, but switched to the cube-root since it was more sophisticated. There's not really any difference other than how the acceleration acts and the fact that the second way compiles 26 bytes smaller. Everyone was right about how bad it was to use a cube-root function, but it did still function normally, it just wasn't as efficient.

Congratulations, you read all of that (did you really?)! If you have any questions or comments, feel free to reply; I'll get a better version out as a GitHub repo when I feel like the code is good enough to see the light of day.
Wow this looks really cool! And it runs smooth so far too, great job!
looks neat Smile

where did you get the sprites from?
Wow, that seems to be looking really good. I'm excited for this project to be completed. Any idea how long it will take to complete it?
tr1p1ea wrote:
Wow this looks really cool! And it runs smooth so far too, great job!


Thanks, I've been optimizing code as I write it, and then going over it again. It's helped to reinforce stuff I've learned, and most of the smoothness comes from it being locked at 25 FPS, it would be fluctuating in the 30's otherwise. My logic is that this way lag can't interfere with the experience, and the 25 FPS is enough to keep it from looking choppy.

Alvajoy123 wrote:
looks neat Smile

where did you get the sprites from?


With the sophisticated method of screenshotting my phone and using MS Paint! I tried to edit them down to size and get them as low-res as possible so they'd fit in a reasonable size. It's about 41 kb without compression right now, down to 4036 bytes right now in it's unfinished state.

RoccoLox Programs wrote:
Wow, that seems to be looking really good. I'm excited for this project to be completed. Any idea how long it will take to complete it?


Most of my coding takes place at night or in my study hall periods, but the lack of a regular sleep schedule is starting to take its toll. I can take an incredible amount of abuse normally, but I've been trying to fix my circadian rhythms lately. Thankfully, school isn't too much of a problem, so most of the work should be in sprites. I hope to have something basic out soon, with proper menus, upgrades, and all that good stuff out over time. Hopefully before October!
How's the project going?
Alvajoy123 wrote:
How's the project going?




I HAVE DONE STUFF WITH THE THINGS.
As you can clearly tell, I have nearly completed the game due to an incredibly productive school week of 3 study halls. If you step back 15 feet it even looks like the real thing! I'm being sarcastic! There's still so much to be done!

I've added some spawnCoin() and spawnZapper() functions that, well, spawn coins and zappers. The coins have animations now, the zappers are still unfinished and need their animations and sparks. Barry also still needs a jetpack, which should be easy and is on the agenda. The zappers are given a random X, Y, and length, calculated so they don't go offscreen, and have a 1/100 chance of spawning each frame. The coin formations are randomly chosen from a multidimensional array, with a 1/200 chance of respawning. That leads to them teleporting around, but I'll have a smart system for the zappers soon and something for coins as well. I have 3 bugs currently that are killing me, and I can't seem to pin down what's causing them as of yet:

1. If you open the program and hold [2nd], then the keypad becomes unresponsive, which also sends Barry up as the [2nd] key is frozen as constantly being pressed, and [clear] stops working so you can't close the program, requires a reset to get out of.

2. If you spam clear quickly while starting the program, the screen freezes white for ~30 seconds and then goes back to normal, with the game running just fine. I can't replicate this, so I may have accidently patched it out since I changed how the loop worked a while back.

3. You can occasionally clip through long zappers, which I can't explain as the hitbox calculation is checking to see if the point Barry is drawn from is at a point where Barry's sprite appears to "collide" with the calculated zapper hitbox. Math doesn't lie, so I can only assume that the check is failing somehow.

I've made a GitHub repo for the project so people can tell me exactly why my code sucks. This is my first "real" C project, and it needs to be incredibly optimized, so I'm sure I've missed a bunch of opportunities to make it better. It's currently compiling at 5,874 bytes, which I find unacceptable. If you want to put it on your calc or pop it into CEmu, feel free to bask in a full 27-36 FPS of unfinished and buggy code! Iif you have any code tips or suggestions then please tell me, I've still got a lot to learn and lots to do.
I made a Jetpack Joyride clone for the CE in ICE a long time ago, but it was nowhere near this awesome. Can't wait for more updates!
Feature creep is a thing to be feared.

I honestly didn't think about how much I could add, just about what I would add. I got those mixed up and made a real mess of the code. I wanted (and still hope) to add an easy way to create custom sprites for the game and store them as appvars that can be selected. I wrote the code around this idea and made it much more difficult for myself. I had an epiphany last week where I suddenly realized how horrible the code was and how I would need to create so many redundancies to make sure that some noob could figure everything out without crashing the calc. I've spent the last while re-writing my code so it's actually compact and efficient, although there are still some improvements to be made. Fixing everything I thought I had fixed took far longer than expected, but here's an update (as late as it is):



You may finally feel relieved, there's a jetpack now! Barry is now no longer levitating, and he has proper animations. This was a serious test of my non-existent art skills, and boy was trying to rotate that jetpack difficult, especially at the low resolution the calc forces me to work with. I've made several optimizations that freed up a lot of space, but you wouldn't be able to tell at this point. It's clocking in at 9186 bytes now, and you can check it out at the repo. I managed to fix all the old bugs on my own, it's amazing what reading through the gfx wiki can clear up. I now have two questions that aren't bugs, but still annoy me to no end:

1. Why is kb_Scan() so slow? It fixed the [clear] bugs and softlock from the last version, but it took off quite a few frames as well. Is there some other way I can update the key register, or only update certain keys?

2. gfx_SwapDraw() is faster and more compact than just blitting, but the FPS count is all over the place, from 26-54 FPS, with 26 being far too close to the 25 cap, which I don't want to hit because strange things happen when the FPS goes below 25. What's the explanation for this behavior and can it be rectified? I know I can make it more efficient, but is there anything that can specifically be done to speed up the drawing?

If you have any questions, comments, or ideas, feel free to share. I'll be working on missiles and lasers for now, along with some more odd debugging if I find anything useful on Stack Overflow.

Argus wrote:
I made a Jetpack Joyride clone for the CE in ICE a long time ago, but it was nowhere near this awesome. Can't wait for more updates!

Huh, I didn't see that in the archives. I wanted this to be a completely fresh project, but I suppose since I'm using C it's still unique enough. Nice to know that my attempts at polishing it up are showing!
Nice work; it's looking awesome Smile

King Dub Dub wrote:
Why is kb_Scan() so slow? It fixed the [clear] bugs and softlock from the last version, but it took off quite a few frames as well. Is there some other way I can update the key register, or only update certain keys?

It's slow because it blocks while it scans the keypad. A better method is to enable continuous scanning of the keypad using the below function. It will automatically keep the registers updated; but note that calling OS functions like GetCSC (and sometimes interrupts!) may change the keypad mode; hence why for the examples it isn't really used.


Code:
kb_SetMode(MODE_3_CONTINUOUS);


King Dub Dub wrote:
gfx_SwapDraw() is faster and more compact than just blitting, but the FPS count is all over the place, from 26-54 FPS, .... blah blah blah... speed up the drawing?


You can use the built-in timers to control the tick rate of the program. Alternatively there is partial redraw; but since the entire screen is basically moving, it becomes a little more difficult. You can speed up the drawing by making your code better too Razz (hint: this is slow af).
When using gfx_SwapDraw, you should try to avoid calling a graphics function immediately after SwapDraw. SwapDraw tells the LCD controller to start switching the two buffers, and while that switch is taking place, all of the graphics functions will block until it finishes.

Right now, you're drawing the background as basically the first thing in your loop, while you call gfx_SwapDraw at the very end of the loop. As a result, a lot of the frame time is spent waiting for the swap to finish, and you could use this time to do non-graphical processing.
I'd recommend reorganizing your loop to run in this order:
    All non-graphical processing, with nothing drawing to the screen or buffer
    All graphical processing, with minimal non-graphical processing
    gfx_SwapDraw

This will allow you to use the time that was previously used to wait for the buffer swap to do meaningful calculations.

As Mateo said, I'd avoid flipping a sprite every frame. Flipping and rotating sprites is very slow, so I would flip each sprite only once at the beginning of the program.

Also, this line is several hours of debugging waiting to happen. The define is basically saying, "replace all instances of "extern" with "MaxCoins 27"", which I'm guessing is not what you want. You don't have to (and can't) specify defines as "extern," as including the header file is enough to allow you to use them. I would recommend just deleting that line, as your program will still build without it.

You also should not declare variables in a header file. If you try to include the header file in two places, two copies of the variable with the same name will be created, which prevents the program from being linked and built. Instead, you should put variables and function definitions in a .c file, and defines, externs, and function declarations in a .h file, like this:
in coinShapes.h:

Code:
#define MaxCoins 27
extern const uint24_t ctx[5][MaxCoins];
extern const uint8_t cty[5][MaxCoins];

in coinShapes.c:

Code:
#include "coinShapes.h"
const uint24_t ctx[5][MaxCoins] = {...};
const uint24_t cty[5][MaxCoins] = {...};

(I also added the const modifier, as you never change the contents of ctx/cty, but that's unrelated to it being in a header)

Finally, I'd recommend removing the bin/ and obj/ folders from your repository. They make it difficult to see what was actually changed in a commit, and are redundant as you can regenerate them from source. If you still want to provide a compiled 8xp download, you should do that in the Releases section on GitHub.

Anyway, great work! This project is looking really neat and I'm looking forward to playing the full release.
commandblockguy wrote:
When using gfx_SwapDraw, you should try to avoid calling a graphics function immediately after SwapDraw. SwapDraw tells the LCD controller to start switching the two buffers, and while that switch is taking place, all of the graphics functions will block until it finishes.


I honestly don't know why the background drawing was before all the math, that's always been a cardinal sin to me, I guess I must've ctrl-z'd there when first adding it in. That's fixed easily, moved right before coin drawing, with the spawnZapper() function moved before it too to maximize the buffer period.

commandblockguy wrote:
As Mateo said, I'd avoid flipping a sprite every frame. Flipping and rotating sprites is very slow, so I would flip each sprite only once at the beginning of the program.


How exactly is one supposed to do that?I tried this as a test of the flipping just to see if it would work:

Code:
    for(i = 0; i < 2; ++i)
    {
        decompressorVar = gfx_MallocSprite(32, 32);
        zx7_Decompress(decompressorVar, electricSheet_tiles_compressed[i]);
        electricFlip[i] = gfx_FlipSpriteX(decompressorVar, electricBuffer);
        electric[i] = gfx_FlipSpriteX(electricFlip[i], electricBuffer);
    }

electripFlip[] is identical to electric[], but I just use it to store the flipped sprites and then flip them back. It gives me this:



Something funky is afoot. What exactly is causing this and what's the recommended way to store the flipped sprites? All my previous attempts resulted in similar broken sprites, and I'm confused as to why flipping across the x-axis twice does this. Trying to draw the sprites directly from electricFlip results in similar sprite errors, although they look a bit more recognizable.

King Dub Dub (asking a dumb question) wrote:
commandblockguy wrote:
If you try to include the header file in two places, two copies of the variable with the same name will be created, which prevents the program from being linked and built. Instead, you should put variables and function definitions in a .c file, and defines, externs, and function declarations in a .h file, like this:
in coinShapes.h:

Code:
#define MaxCoins 27
extern const uint24_t ctx[5][MaxCoins];
extern const uint8_t cty[5][MaxCoins];

in coinShapes.c:

Code:
#include "coinShapes.h"
const uint24_t ctx[5][MaxCoins] = {...};
const uint24_t cty[5][MaxCoins] = {...};

(I also added the const modifier, as you never change the contents of ctx/cty, but that's unrelated to it being in a header)


You managed to explain that better than 45 minutes of googling back when I first tried to incorporate headers; and my first attempts are also why there was a #define extern MaxCoins, I did that when I was messing around. Looks like that somehow didn't cause any problems, no idea how I got away with that for so long! Compiling the header examples fails though with "syntax errors" at the start of the [5] for the ctx and cty arrays in both coinshapes.h and coinshapes.c. The compiler isn't any more helpful than that though, is there anything else that I'm missing here?

SAX wrote:
8:14:47 PM [#] [#] [commandz] I would maybe try adding #include <stdint.h> at the top of the header
The issue with the flipping code is that you're allocating a single sprite, then trying to store two copies of the sprite to it.
gfx_FlipSpriteX always returns the second argument you pass it. I'm not entirely sure why it does this - it makes it more confusing for people who aren't experienced with using pointers, so in my opinion, it just shouldn't return anything. This makes it more clear that the second argument is the output, and that the flipped version of the input is copied to it.

Anyway, as a result, you're setting electricFlip[i] to electricBuffer, and when you call gfx_FlipSpriteX the second time, the arguments are basically (electricBuffer, electricBuffer), which is the same input and output buffer, which doesn't work.

Even if the function did work in-place, this code definitely wouldn't do what you expect. electricBuffer has a single location in memory, and each element of electric is a pointer that refers to a particular location in memory. Doing electric[0] = electricBuffer; causes electric[0] to point to the location of electricBuffer, rather than copying data from electricBuffer into electric[0]. As a result, if you change the contents of electricBuffer afterwards, electric[0] would also appear to change. If you set all of the elements in electric to the location of electricBuffer, all of the sprites would display as whatever sprite was last copied into electricBuffer, either by decompressing or flipping.

So, you want to make sure that each item of electric points to a different location in memory. This is what gfx_MallocSprite is for - each time you call it, it will give you a new location in memory that you can use without affecting any of the other sprites. Since you want to make two new sprites per loop, you'll want to call gfx_MallocSprite twice, like so:


Code:
for(i = 0; i < 2; ++i)
{
    electric[i] = gfx_MallocSprite(32, 32);
    electricFlip[i] = gfx_MallocSprite(32, 32);
    zx7_Decompress(electric[i], electricSheet_tiles_compressed[i]);
    gfx_FlipSpriteX(electric[i], electricFlip[i]);
}
Well, It's been what... almost three weeks? I'm embarrassed to admit it took this long to get an update, but there are now missiles!



I've also gone and re-skinned and sized the coins, since they weren't the correct size compared to the vertical scaling of the rest of the game (which is a 1 : 0.2899 ratio for everything except Barry, since his sprite doesn't look to good scaled down). Most of this time has been trying to find a way to make the missiles oscillate like they do in the game, which is why they're just static images for now. The real problems for this so far have been that I can't find a (good) way to make a linear equivalent of the wave formula, and Mateo updated convimg so that it is no longer backwards compatible with older yaml's, so almost every project is now outdated (including the CEdev examples). After some fighting I somehow got it to work through trial and error, but I didn't get much productive stuff done.

Commandz: I did the flippity things, stuff is smaller and better now (although I still managed to make a spaghetti mess with the zappers)!

MateoConLechuga wrote:
You can use the built-in timers to control the tick rate of the program. Alternatively there is partial redraw; but since the entire screen is basically moving, it becomes a little more difficult. You can speed up the drawing by making your code better too Razz


I'm sorry I forgot to thank you too Mateo, but what do you mean by "tick rate" here? I've got a system with a delay that changes so that each run of the loop takes the same amount of time, but I assume you know that. Is this faster/smaller than what I've been doing?


Code:
//FPS counter:
frameTime = (32768 / timer_1_Counter);

if (frameTime > 25)
{
      delay(40 - (1000/frameTime));
}

timer_1_Counter = 0;
It's been awhile since I've looked at this topic, but I'm really liking how this project is going. Good job King Dub Dub.
How much longer until it might be released? How many more things do you have left to add into the program?
Is this done yet
RoccoLox Programs wrote:
It's been awhile since I've looked at this topic, but I'm really liking how this project is going. Good job King Dub Dub.
How much longer until it might be released? How many more things do you have left to add into the program?
MateoConLechuga wrote:
Is this done yet


No. No it's not. BUT that will change soon whether it kills me or not!

All I need before I feel good about uploading to the archives is:
1. Menuing
2. Finished Missile animations
3. Lasers
4. Fix the bug that breaks the USB that I discovered last night
5. Minor optimizations

This part might be the end of me, mainly since I have no clue how to make a non-linear menuing system that looks nice, since the buttons will be in a sort of L-shape. I have an idea but it's not very smart, so I don't like it (even though it will work, and with only a few if statements).

I'm working on the missile animations, my productivity has skyrocketed since something clicked when I was using GIMP the other day and now I can smart-select and dither with ease. Should make the animation pulling a breeze (although if I could crack the fake .tex file type then I could just rip them).

Lasers are going to be easy, but I'll need at least 4 variables (X-displacement, Y-pos, final Y-pos, timer) and I've been trying to think of ways that won't kill performance.

Yeah, there's been a bug with the USB for some time that I didn't think was my program; it makes the USB stop working until the calc powercycles and freezes it when TI-Connect tries to send files. I've been deleting blocks of code and I've isolated it to the sprite decompression, I have some theories about the latest optimizations writing to some part of USB that they shouldn't, so I'll be rebuilding the malloc( part today and updating the github.

I plan on making a few optimizations with using tilemapping to draw the backgrounds and then moving on to create some sloppy-but-working game that I can upload. The size might be large, but I just want to get a playable version out for people to break right now so I can collect some playdata and fix sneaky bugs.

I know I did say I wanted it done by October, but clearly I was wrong. I have made good progress, but bugs and learning curves haven't been helping (the amount of "smart" code I have to build and test to compare size and performance benchmarks is getting annoying, especially since the ugliest code tends to win). I'm still fairly new to C, so progress is agonizingly slow. I've been getting faster and better lately, so it should be out soon, absolutely before Christmas; and if it still isn't out, you can yell at me and take away my altoid tin collection, since that would be horrible. Anyway, no more excuses, Im'ma go think of some more bugfixes.
Looking very polished thus far and is running at a really nice framerate when you consider how much is onscreen. Have you got some menu stuff already, or is that something you need to make from scratch?

Regarding USB you could try the _SetupHome syscall before you exit?
King Dub Dub wrote:
I've been getting faster and better lately, so it should be out soon, absolutely before Christmas; and if it still isn't out, you can yell at me and take away my altoid tin collection, since that would be horrible. Anyway, no more excuses, I'mma go think of some more bugfixes.

This is good news for MY altoid tin collection! Razz Joking aside, this is looking really cool! I am super excited to try this out, and good luck in the completion of the project!
TIny_Hacker wrote:
King Dub Dub wrote:
I've been getting faster and better lately, so it should be out soon, absolutely before Christmas; and if it still isn't out, you can yell at me and take away my altoid tin collection, since that would be horrible. Anyway, no more excuses, I'mma go think of some more bugfixes.

This is good news for MY altoid tin collection! Razz Joking aside, this is looking really cool! I am super excited to try this out, and good luck in the completion of the project!

I can't wait to see this completed! Good luck King Dub Dub.
  
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 GMT - 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