Author Topic: Problem with shooter code  (Read 15769 times)

0 Members and 1 Guest are viewing this topic.

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #15 on: August 04, 2013, 04:13:11 am »
So heres another interesting problem (math oh noes):
Right now bullets can only move up/down depending on a value controlling that. Pretty much thats kinda boring and I wanted bullets to sorta drift to the side a bit towards a player (if you guys have played galaga) when fired by enemies to make it a bit more difficult. Lets say the enemy ship was at 3,30 and you were at 1,10. Normally I'd just make another value for the Y direction per cycle and base it off the slope between those points (-.1). Adding this to the current Y every cycle would just be ignored until it hit a X position like 20, when it would finally be at 2 (technically at least, with calculator math I think it rounds down so it would be 2 right off the start but thats close enough). Problem is that uses floating points and signed numbers which seems really difficult to do, so I was thinking why not just add 4 extra bytes to each bullet, 2 being the x and y it was fired from and 2 more for the x and y destination. Because the bullet will move 1 pixel per cycle down, the slope could be calculated every cycle and only add/subtract the position if it actually equals something (e.g. (1/10)*2, nothing (1/10)*10 returns 1), but this still calls for signed numbers and some pretty complex math to be done over and over. So knowing that people here have done really amazing looking shooters before, I thought someone might have some magical solution to this problem or something. If not I can just have the enemies shoot straight down but yea.
« Last Edit: August 04, 2013, 04:20:42 am by LemonDrop »

Offline Streetwalrus

  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3821
  • Rating: +80/-8
    • View Profile
Re: Problem with shooter code
« Reply #16 on: August 04, 2013, 04:50:50 am »
What you want is fixed point math, which is pretty fast. Also take a look at Bresenham's algorithm. It's a very simple line drawing algorithm and I'm sure it can be used to move a bullet around. ;)

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #17 on: August 04, 2013, 05:37:35 am »
What you want is fixed point math, which is pretty fast. Also take a look at Bresenham's algorithm. It's a very simple line drawing algorithm and I'm sure it can be used to move a bullet around. ;)
Yea thats what I am looking for, but I have no idea how I would implement that. Also that looks like it can only determine if a point is supposed to be where it is, the main problem I am having is how to calculate a points position in the first place given its Y value.

Offline Streetwalrus

  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3821
  • Rating: +80/-8
    • View Profile
Re: Problem with shooter code
« Reply #18 on: August 04, 2013, 06:11:32 am »
Basically for fixed point math, you use the most significant byte (MSB) for the integer part and the least significant byte (LSB) for the decimal part.
Then addition/substraction is the same (just make sure to multiply your integers by 256). Multiplying/dividing by an integer is also the same and Axe has some routines if you want to multiply/divide two fixed point numbers together. ;)

Offline shmibs

  • しらす丼
  • Administrator
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2132
  • Rating: +281/-3
  • try to be ok, ok?
    • View Profile
    • shmibbles.me
Re: Problem with shooter code
« Reply #19 on: August 04, 2013, 05:09:13 pm »
a simpler, faster method to manage this would be to just make your playing area be larger than the actual screen resolution by some factor of two. then you can accomplish this with only a single slope calculation when the bullet is initially fired and without using anything but simple integers. what this looks like in realisation would be having a one byte each for x and y positions (or two for x, if you choose a factor greater than two and thus end up with more than 192 horizontal logical pixels mapped to your 96 physical pixels), and one byte each for the x and y velocities (or a nibble, if you want to conserve space). then just add the velocities to the positions each frame and then map the resulting logical positions to their physical positions with a quick division by your chosen factor of two (sure, other factors could be used, but they would be MUCH slower). thus, if you chose a factor of four and only set the x velocity to 1, your bullet would only "drift" over one physical pixel every 4 frames.

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #20 on: August 04, 2013, 05:19:53 pm »
a simpler, faster method to manage this would be to just make your playing area be larger than the actual screen resolution by some factor of two. then you can accomplish this with only a single slope calculation when the bullet is initially fired and without using anything but simple integers. what this looks like in realisation would be having a one byte each for x and y positions (or two for x, if you choose a factor greater than two and thus end up with more than 192 horizontal logical pixels mapped to your 96 physical pixels), and one byte each for the x and y velocities (or a nibble, if you want to conserve space). then just add the velocities to the positions each frame and then map the resulting logical positions to their physical positions with a quick division by your chosen factor of two (sure, other factors could be used, but they would be MUCH slower). thus, if you chose a factor of four and only set the x velocity to 1, your bullet would only "drift" over one physical pixel every 4 frames.
Yea this is what I was thinking about doing. Thanks for the help.

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #21 on: August 04, 2013, 10:19:44 pm »
So I decided that a 2x logical grid would allow for enough precision and I want to make it 10x the size of the screen, but I am not sure about how to do some stuff. Firstly I decided to make the x and y speeds into signed numbers just for convenience, but I do not know how to make a number signed and dont know if it works with normal math like Adding a signed number to a non signed one (e.g. 2+(-1) equaling 1 like it should). Also to make the logical grid that big, I would have to use 16 bit numbers which I know take up 2 bytes but I dont know how to create them and again dont know if they work with non 16 bit numbers (final product being the signed x and y speeds are added to 16 bit x and y positions, which are then divided by 10 and displayed to the screen). Sorry for asking so many questions but theres not much stuff about axe I could find on the internet.

Offline shmibs

  • しらす丼
  • Administrator
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2132
  • Rating: +281/-3
  • try to be ok, ok?
    • View Profile
    • shmibbles.me
Re: Problem with shooter code
« Reply #22 on: August 04, 2013, 11:11:56 pm »
there are no "signed" and "unsigned" integers in axe. all integers are the same. the following from the somewhat-outdated but still useful Documentation.pdf explains how this works out:

Spoiler For "quote from Documentation.pdf:
Alright, now to the fun stuff! Okay, this is one of the most important differences between
Axe and BASIC. Numbers in Axe are all 16-bit integers meaning that there's no such
thing as fractions and decimals. What the 16-bit part of it means is that a number can
only hold a value between 0 and 65,535. This is called the unsigned number system
meaning that there is no sign: all the numbers are positive.
Now wait a minute you say, what if I want to use negative numbers? Well in that case,
you want to use signed representation. The way that works is that we cut our range in
half and say that all the numbers on one side are positive and numbers on the other
side are negative. So numbers from 0 to 32767 we still say are positive but now the
numbers from 32768 to 65535 we say are actually -32768 to -1. So our new range is
-32,768 to 32,767
Remember, both representations are really the exact same number. It's just a different
way of representing it. So -1 really is the same number as 65535. And I'm not just
making this up, the mathematics works this way. If you add 65535 to a number you get
exactly the same result as if you subtracted 1! How the heck does that happen? That
brings me to my next point which is modular arithmetic.

Remember, we can only hold values between 0 and 65535 right? Well what happens if
we keep adding and overflow the maximum value? Let's count by constantly adding 1:
0,1,2,3,...,65533,65534,65535,0,1,2,3...
Do you see what happened? Once you pass the maximum, you loop around back to 0
again. Signed representation does the same thing, best illustrated by this xkcd comic:
[image with a fellow counting sheep here. when he gets to 32,767, he loops back
around to -32,768 and starts counting up]

basically, what this means is that you can just use plain integers and not worry about it (unless you're using division, in which case a single division symbol will yield an unsigned division while two symbols will yield a signed division).

as for single and multi-byte numbers, all of axe's variables are two-byte numbers by default and all referenced positions are single-byte numbers by default. if you want to access a single byte of a variable, you have to use the variable's location to reference it, and, if you want to read some given location as a two-byte number, you add a ^r (that's Angle+3) after the curly braces (so something like {Pic1+8}^r, for example).


EDIT: also, please don't double post (post twice consecutively in the same topic under 24 hours). if you use the "Modify" button to edit your post (like i did just now with this post), the topic will be marked as unread again for everyone.
« Last Edit: August 04, 2013, 11:14:50 pm by shmibs »

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
Re: Problem with shooter code
« Reply #23 on: August 04, 2013, 11:59:46 pm »
Hey LemonDrop, I am not sure if this is the Bresenham method, but this is a line drawing algorithm I came up with a few years ago that is fast and easy to implement in Axe, Assembly, BASIC, Grammer -- you name it. Modified, instead of drawing a line, you can make a bullet follow a trajectory. This will also work smoothly using the the inflated coordinates that shmibs was referring to (this is an excellent technique, especially when you start doing physicsy things) or just the regular 96x64 pixel area. Anyways, the basic pseudo-code looks like this:
Code: [Select]
;Given : (x1,y1) and (x2,y2)
x2-x1 → width
y2-y1 → height
1 → xinc
1 → yinc
If width>0
1 → xinc
Else
-1 → xinc
-width → width
If height>0
1 → yinc
Else
-1 → yinc
-height → height
If width=0
y1 → count
while count <= y1+height
plotpixel(y1,x1)
x1+1 → x1

else
width → accumulator
width*2 → width
height*2 → height
0 → count
while count < width
plotpixel(y1,x1)
y1+yinc → y1
accumulator - height → accumulator
while accumulator < 0
x1 + xinc → x1
plotpixel(y1,x1)
accumulator + width → accumulator
plotpixel(y1,x1)
While that may look complicated, it actually simplifies quite a bit when put in use. To describe the algorithm, there is an accumulator that starts at 1/2 the width (because we are using integers, I store the width to the accumulator and then double width and height, so the accumulator is half the width). Then at every cycle, a much more general algorithm might increment y and add height/width to to x. However, we cannot use non-integers, so we need to be more clever. This is why I have an accumulator. What we could do is add height to the accumulator and if the acc>width, then we need to increment the x coordinate. To determine how many times we need to increment, just subtract accumulator-width until accumulator<width, each time incrementing x and plotting a pixel. In the algorithm above, it is more optimised for assembly and instead of doing accumulator+height, I do accumulator-height until accumulator<0 (which the processor automatically recognises without needing to do a compare).


Anyways, now for some actual Axe code! (Note: I am not a very knowledgeable Axe coder, so there may be many optimisations to be had!) The first thing we are going to need to take note of is that we aren't drawing a whole line at once (unless you are making a laser effect) so it will be more useful to make a subroutine that returns the coordinates of the next pixel. As well, in the event that we have multiple bullets on screen, we might want to make the routine even more flexible to work with a buffer of bullet data so that we don't tie up variables.
Here we go:
Code: [Select]
Lbl BNEXT
.IN: Ptr
.accumulator,dir,x,xinc,w, y,yinc,h,counter
{r1}→r3
!If {r1+1}
r1+4→r1
{r1++)→r2+{r1++)→r2
r3-{r1++}→r3→{r1-8}
r3<<0→{r1-7}
Else
r1+1→r1
{r1++)→r2+{r1++)→r2
r3+{r1++}→r3→{r1-5}
r3<<0→{r1-4}
r1+3→r1
End
{r1-5}→X
{r1-2}→Y
If {r1++}--
Return
End
r1-8→r1


Lbl DELB
.REMOVE THE BULLET
Return!If {GDB1)
Exch(GDB1Z,r1,9)
{GDB1}--
Return

Lbl ADDB
.IN: (x1,y1,x2,y2)
ReturnIf {GDB1}=10
{GDB1}++→r6*2*2*2+r6+GDB1-9→r6

r3-r1→{r6++}→r5=0→{r6++}
r1→{r6++}
0→{r6++}
If r6>0
1→{r6}
ElseIf r6>32767
-1→{r6}
-r5→r5
End
r5→{r6++}
r5→{r6+4}

r4-r5→{r6++}→r5=0→{r6++}
r2→{r6++}
0→{r6++}
If r6>0
1→{r6}
ElseIf r6>32767
-1→{r6}
-r5→r5
End
r5→{r6++}
Return

I have not tested that code, so I doubt it will work, but just in case it does, GDB1 should point to a buffer large enough to hold the bullet data (in the code above, it limits to 10 bullets, so 9*10+1 = 91 bytes). This buffer should be zeroed, and GDB1+9*9+1→GDB1Z should be defined (GDB1Z points to the last bullet).
The 3 routines, if they work, are:

BNEXT(ptr) : ptr points to 9 bytes of bullet data. Returns X,Y as the coordinates of the bullet.
DELB(ptr)  : ptr points to the 9 bytes of the bullet data to remove from the bullet buffer.
ADDB(x1,y1,x2,y2) : If there is room on the bullet buffer, the bullet trajectory is added.

As a note, BNEXT automatically removes the bullet if it reaches its destination coordinate. If you want it to continue past the destination until it goes offscreen, the code can be modified.


I hope it works, but I am too tired to test it tonight. I need sleep :P

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #24 on: August 05, 2013, 06:34:10 pm »
-lots of helpful stuff-
Ok so I spent the night writing my own axe test code based on the way I store data and calculate bullets and came up with this based off the way you explained your math calculations:

But as you can see it really doesn't work too well. Heres the source of the test:

Code: [Select]
.ANGLEA
[00003C3C3C3C0000]->Pic1
[0000001818000000]->Pic2
DiagnosticOff
ClrDraw
DrawInv
StorePic

.FIRING POS: 44,25
30->X
54->Y
0->B
Repeat getKey(15)
RecallPic
sub(D
DispGraph
If getKey(2) and (X!=1
X-1->X
End
If getKey(3) and (X!=87
X+1->X
End
If getKey(4) and (Y!=1
Y-1->Y
End
If getKey(1) and (Y!=55
Y+1->Y
End

.BULLET STRUCUTRE: {PTR-7}-None {PTR-6}-Accumulator {PTR-5}-Width {PTR-4}-Height
.{PTR-3}-XSpeed {PTR-2}-YSPEED {PTR-1}-X {PTR}-Y
!If rand^(8)
.MAKE NEW BULLET
B+1->B*8+L1->I
25->{I}
44->{I-1}

.SET X AND Y SPEED (2 being 1, 0 being -1)
If 25>Y
0->{I-2}
25-X->{I-4}
Else
2->{I-2}
X-25->{I-4}
End

If 44>X
0->{I-3}
44-X->{I-5}
Else
2->{I-3}
X-44->{I-5}
End
.SET ACCUMULATOR, W, H (I-7 is nothing)
{I-5}->{I-6}
{I-5}*2->{I-5}
{I-4}*2->{I-4}
0->{I-7}
End

For(I,1,B
8*I+L1->J

.CALCULATE BULLETS POSITION
If {J-6}>{J-5}
{J-1}+{J-3}-1->{J-1}
{J-6}-{J-5}->{J-6}
Else
{J}+{J-2}-1->{J}
{J-6}+{J-4}->{J-6}
End

.DELETE OFFSCREEN BULLETS
If ({J}=57) or ({J}=0) or ({J-1}=94) or ({J-1}=0)
8*B+L1->K
Copy(K,J,8)^^r
B-1->B
I-1->I
End
End
End

Lbl D
.DISPLAY BULLETS/SHIPS
For(I,1,B
8*I+L1->J
Pt-Change({J-1},{J},Pic2)
End
Pt-Change(44,25,Pic1)
Pt-Change(X,Y,Pic1)

Is there something wrong with it which would make the bullets not really target the player (ignoring the check for if width=0, I skipped that because its easy to do)? Or is this just how its supposed to work.
« Last Edit: August 05, 2013, 06:51:30 pm by LemonDrop »

Offline Jonius7

  • python! Lua!
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1918
  • Rating: +82/-18
  • Still bringing new dimensions to the TI-nspire...
    • View Profile
    • TI Stadium
Re: Problem with shooter code
« Reply #25 on: August 05, 2013, 10:25:01 pm »
That's weird, sometimes there's some sort of delay of the bullets changing direction as the player moves around the screen, sometimes it happens much more quickly
Code: [Select]
8*I+L1->J
So that definition defines J, which then calculates the bullets' positions. Could this be it? Also how is the code for taking the player's position on the screen taken into account?
« Last Edit: August 05, 2013, 10:33:02 pm by Jonius7 »
Programmed some CASIO Basic in the past
DJ Omnimaga Music Discographist ;)
DJ Omnimaga Discography
My Own Music!
My Released Projects (Updated 2015/05/08)
TI-nspire BASIC
TI-nspire Hold 'em
Health Bar
Scissors Paper Rock
TI-nspire Lua
Numstrat
TI-nspire Hold 'em Lua
Transport Chooser
Secret Project (at v0.08.2 - 2015/05/08)
Spoiler For Extra To-Be-Sorted Clutter:

Spoiler For Relegated Projects:
TI-nspire BASIC
Battle of 16s (stalled) | sTIck RPG (stalled) | Monopoly (stalled) | Cosmic Legions (stalled)
Axe Parser
Doodle God (stalled while I go and learn some Axe)

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #26 on: August 05, 2013, 10:30:09 pm »
That's weird, sometimes there's some sort of delay of the bullets changing direction as the player moves around the screen, sometimes it happens much more quickly
Code: [Select]
8*I+L1->J
So that definition defines J, which then calculates the bullets' positions. Could this be it? Also how is the code for taking the player's position on the screen taken into account?
If you look at the code where the bullets are created, you can see that X and Y are subtracted in a way that gives a width and height value. Because there can be no signed numbers, I check to see if they are less or greater than the fixed position of the enemy (44,25) and then set the "x and y speed" accordingly so when the operations are preformed later it simply adds that value minus one to the x or y position of the bullet when needed.

Its pretty hard to explain and its based off the algorithm the person above that post came up with so any more information lies in there.

Offline Jonius7

  • python! Lua!
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1918
  • Rating: +82/-18
  • Still bringing new dimensions to the TI-nspire...
    • View Profile
    • TI Stadium
Re: Problem with shooter code
« Reply #27 on: August 05, 2013, 10:33:13 pm »
I've been looking at the behaviour and I may have another idea why it's not completely working, though it's hard to explain and I'm not sure it happens all the time. When you move vertically up, your x value doesn't change, perhaps your program isn't always calculating the change in y value, and because the x value is not changing, the program isn't calculating a new angle for the bullets to shoot to.

Just a suggestion.
« Last Edit: August 05, 2013, 10:33:32 pm by Jonius7 »
Programmed some CASIO Basic in the past
DJ Omnimaga Music Discographist ;)
DJ Omnimaga Discography
My Own Music!
My Released Projects (Updated 2015/05/08)
TI-nspire BASIC
TI-nspire Hold 'em
Health Bar
Scissors Paper Rock
TI-nspire Lua
Numstrat
TI-nspire Hold 'em Lua
Transport Chooser
Secret Project (at v0.08.2 - 2015/05/08)
Spoiler For Extra To-Be-Sorted Clutter:

Spoiler For Relegated Projects:
TI-nspire BASIC
Battle of 16s (stalled) | sTIck RPG (stalled) | Monopoly (stalled) | Cosmic Legions (stalled)
Axe Parser
Doodle God (stalled while I go and learn some Axe)

Offline LemonDrop

  • LV2 Member (Next: 40)
  • **
  • Posts: 26
  • Rating: +4/-0
    • View Profile
    • tin.gy
Re: Problem with shooter code
« Reply #28 on: August 05, 2013, 11:02:32 pm »
I've been looking at the behaviour and I may have another idea why it's not completely working, though it's hard to explain and I'm not sure it happens all the time. When you move vertically up, your x value doesn't change, perhaps your program isn't always calculating the change in y value, and because the x value is not changing, the program isn't calculating a new angle for the bullets to shoot to.

Just a suggestion.
I really dont think thats the problem, or atleast I dont think that would happen in axe, but I'll check it out.

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
Re: Problem with shooter code
« Reply #29 on: August 05, 2013, 11:19:00 pm »
Hmm, I recognise the problem, but I did not see the issue in your source code immediately. Hopefully I will take a look at it tomorrow and possibly figure out the issue.

I would also like to point out that you can do signed comparisons. For example, {J-6}<<0 to see if it went below zero. I think Axe probably does an auto-optimisation for that.


I tried my attempt above and found that it doesn't work (I forgot some of the nuances of Axe x.x). I did get it to work in BASIC, though.