Spherical forums

Sphere Development => Sphere Support => Script Support => Topic started by: Xenso on July 04, 2013, 03:43:01 pm

Title: Shooting and Collision Detection
Post by: Xenso on July 04, 2013, 03:43:01 pm
How can I program a simple shooting system like in Arkista's Ring for the NES
(http://www.emuparadise.me/Nintendo%20Entertainment%20System/Titles/Arkista's%20Ring%20(U).png)
(http://www.emuparadise.me/Nintendo%20Entertainment%20System/Snaps/Arkista's%20Ring%20(U).png)

The player presses a button, lets say space-bar and a bullet sprite is spawned in front of the player that moves forward at a fixed speed, it then destroys itself when it hits a wall or any other entity. I know how it would work but I'm not a programmer at least yet.
I would need a bullet sprite that creates itself from the location of the players co-ordinates and then moves in the direction the player is facing until it hits an object. A variable could store the players direction but I'm a bit shaky on how to do all this.
I'm reading the Wiki but I learn best when I just dive right in and use the knowledge I learn practically with some help from experienced programmers like Randnen and allot of you (^_^).
Title: Re: Shooting and Collision Detection
Post by: DaVince on July 04, 2013, 04:26:27 pm

The player presses a button, lets say space-bar and a bullet sprite is spawned in front of the player that moves forward at a fixed speed, it then destroys itself when it hits a wall or any other entity. I know how it would work but I'm not a programmer at least yet.
I would need a bullet sprite that creates itself from the location of the players co-ordinates and then moves in the direction the player is facing until it hits an object. A variable could store the players direction but I'm a bit shaky on how to do all this.
I'm reading the Wiki but I learn best when I just dive right in and use the knowledge I learn practically with some help from experienced programmers like Randnen and allot of you (^_^).

Well, you basically dissected the problem! That's a programmer's way of thinking. :)

Sorry for the wiki being so incomplete! We lost a lot of articles some time ago. But the function list should give you an idea of what each function does, anyway.

In this case, it might be useful to check out the following functions to help you: CreatePerson(), DestroyPerson(), SetPersonXYFloat(), IsPersonObstructed(), SetPersonScript(), GetPersonDirection(), QueuePersonCommand(), SetPersonSpeed(). Have the bullet act as a person and use these functions to control it in the way you mentioned, basically. You can also ask me why I'd suggest some of these functions if you can't figure it out. :)
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 05, 2013, 04:56:32 am
Hey thanks  ;)
And yes I would like to ask you why you chose SetPersonXYFloat(). Doesn't Float have something to do with numbers with decimals? I'm guessing this is more precise.
The rest make sense to me but I need to check out YOUR (Davince's) scripting tutorial to catch up with some basic coding. Sphere's still beautiful though and pregnant with possibilities  ;D.
Title: Re: Shooting and Collision Detection
Post by: DaVince on July 05, 2013, 06:04:17 am
Quote
And yes I would like to ask you why you chose SetPersonXYFloat(). Doesn't Float have something to do with numbers with decimals? I'm guessing this is more precise.

It's not the floating point which is important there, but the fact that you can set the person's x and y position at the same time. There's no SetPersonXY() for some reason. But you can also use SetPersonX() and SetPersonY() if you want; it'll just be two functions then. :)

Quote
The rest make sense to me but I need to check out YOUR (Davince's) scripting tutorial to catch up with some basic coding. Sphere's still beautiful though and pregnant with possibilities  ;D.

Drat! Time to properly format some of the later chapters! :P
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 05, 2013, 11:36:15 am
I went through all of it today, it was fine but I skipped the object section for now. Its a lot though and thanks for the help again. I'll get something going maybe tomorrow or later. I'm wiped out right now (-_-) but it was very helpful. I forgot a lot of simple things (^_^).
Title: Re: Shooting and Collision Detection
Post by: N E O on July 05, 2013, 03:51:38 pm
Moved to Script Support.

Regarding existing shooter code to study, I'd recommend studying my Artyxx tech demo once I clean it up. It's a little advanced and attempts to handle collision both in and out of the default map engine.
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 05, 2013, 04:05:31 pm
That would be great if you could share it (^_^)  but I will make a simple script.
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 05, 2013, 04:42:19 pm
You know there is a good code example I made in the topic here: http://forums.spheredev.org/index.php/topic,55.0.html

That should get you on the right track, but it does require you know a bit about programming in JS (technical level = moderate).
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 07, 2013, 03:09:41 am
Code: [Select]

function CreateBullet(hero)
{
    var d = GetPersonDirection(hero);
    var x = 0, y = 0;
    switch(d) {
        case "north": y = -1; break;
        case "south": y = 1; break;
        case "west": y = -1; break;
        case "east": y = 1; break;
    }


I was studying your code and have 2 questions:
Why is it Y only, that is set-up, I thought with computer co-ordinates, If the top left of the computer screen has co-ordinates of X = 0 and Y = 0 then:

North would be a +Y number
East would be a +X number
South would be a -Y number
West would be a -X number

Also I though we would create the bullet in front of the player so it doesn't check if its been obstructed when its created over the player/hero.
If my player is 16 pixels all round, I'm guessing Sphere checks X and Y positions from the center of the sprite ( I hope so ). So the bullets XY co-ordinates would need to be + or - 8 ( half of 16 ) from the players XY co-ordinates. So the code for the case statements would be.

        case "north": y = +8; break;
        case "east": x = +8; break;
        case "south": y = -8; break;
        case "west": x = -8; break;
       
Or I might be misunderstanding something.

the second question is I noticed the arguments in the bullet.push:

Start_x = GetPersonX(hero) + x*16
Start_y = GetPersonY(hero) + y*16

how did you come to this? I'm a bit confused. 
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 07, 2013, 04:01:01 am
You are right the top-left is (0, 0) which is why I'm right in the direction vectors.

Y is up. Going up means you head towards 0, which is a negative number. ;)

North would be a -Y number
East would be a -X number
South would be a +Y number
West would be a +X number

This code:
Start_x = GetPersonX(hero) + x*16
Start_y = GetPersonY(hero) + y*16

Moves the bullet one square ahead of the player. Think about grabbing the players position and then adding to it the direction vector times the tile size (which is 16). You thought right when you said we need to create it in front of the player. This is how it's done. ;)
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 07, 2013, 05:27:26 am
 :) It makes sense.

Whats a direction vector, I'm not getting it on Wikipedia (http://en.wikipedia.org/wiki/Direction_vector) and need some freshening up on my maths  :o  ::).

I get the code after some dry testing and I think we need to use x for east and west:

Start_X = GetPersonX(hero) + x*16

example: hero is facing north at co-ordinates (hero_x,hero_y)

Start_X = hero_x + (0)*16 //case is north so y = -1 and x remains as 0
Start_X = hero_x + 0
Start_X = hero_x

therefore x is the same co-ordinates as our hero

Start_Y = hero_y + (-1)*16
Start_Y = hero_y - 16

example: hero is facing east, same generic co-ordinates.

Start_X = hero_x + (0) //case east, y = 1 and x = 0
Start_X = hero_x

but it never started at east 16 pixels. wont we need to need to change the case statement

Quote

North would be a -Y number
East would be a -X number
South would be a +Y number
West would be a +X number


case "east" : x = -1; break;
case "west" : x = 1; break;
//the rest north and south are the same as previous case code
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 07, 2013, 06:23:58 am
You are absolutely right. The y's on east and west should be changed to x's.

I just changed the original source, thank you. :)

There are so, so many vector pages on Wikipedia it's almost not worth searching. :/

A "direction vector", is well just my loose term for a vector in general (all vectors encode a direction). A vector is basically an integer that encodes a speed and direction. -1 is a speed of 1 pixel going down. If it were -2, it would be a speed of 2 pixels going down, and things would be placed twice as far away from the player character.

It was a neat way of showing how to encode a direction mathematically from the players direction. Of course your idea of literally adding +/- 8 or 16 pixels will do the same thing, but just not as adaptable code-wise.
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 07, 2013, 08:40:07 am
Yeah your method is much neater, thanks I remember vectors. Wikipedia really confused me, I was getting worried for nothing.


Code: (javascript) [Select]
 if (IsPersonObstructedAt(x, y)) {this.dead = true;}



how does the computer know the co-ordinates of x,y


Code: (javascript) [Select]
function CreateBullet(hero)
{
    var d = GetPersonDirection(hero);
    var x = 0, y = 0;
    switch(d) {
        case "north": y = -1; break;
        case "south": y = 1; break;
        case "west": x = -1; break;
        case "east": x = 1; break;
    }

    bullets.push(new Bullet("bullet: " + bullet_num, GetPersonX(hero) + x*16, GetPersonY(hero) + y*16, x, y);
}



I thought x and y where local not global variables in function CreateBullet();


CODE EDITED
Title: Re: Shooting and Collision Detection
Post by: DaVince on July 07, 2013, 08:50:32 am
Just a note: it's always better to put code in [code=javascript][/code] tags, even when you're citing code. Because JS code like [i] will disappear as it's interpreted as bbcode. :)
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 07, 2013, 02:43:23 pm
Oh wow, there are q few issues with it.

Bullet needs a speed member:
Code: (javascript) [Select]

function Bullet(name, start_x, start_y, vel_x, vel_y)
{
    this.name = name;
    this.xVelocity = vel_x;
    this.yVelocity = vel_y;
    this.speed = 1;

    CreatePerson(name, "bullet.rss", true); // name of this bullet;
    SetPersonX(name, start_x);
    SetPersonY(name, start_y);
    IgnoreTileObstructions(name);
}


And you are right about x and y, I wanted to have local variables:
Code: (javascript) [Select]

Bullet.prototype.update = function() {
    var x = GetPersonX(this.name) + this.xVelocity * this.speed;
    var y = GetPersonY(this.name) + this.yVelocity * this.speed;

    SetPersonX(this.name, x);
    SetPersonY(this.name, y);

    if (IsPersonObstructedAt(x, y)) {
        this.dead = true;
        var name = GetObstructingPerson(this.name, GetPersonX(this.name), GetPersonY(this.name));
        if (name != "") {
            // here we have an obstructing entity..
        }
    }
}


I'll update the source as well, yikes!
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 07, 2013, 03:55:34 pm
Programmings just like that though, such small things are easily missed out and can be hard to realize.
;) Its a great reference for a shooting-bullet code though, thank you so much.

I'm having trouble implement it.

for the off-map representation of the bullet, I threw it in a Bullet.js script file

same with the code for when your hero creates a bullet but I think I need an if-statement and GetKey(); function for the trigger-button/input from the player. I think this might need to be in an update or game script file.

the code that is attached to the map engine I'm guessing could go in a seperate script for the general map engine

I think the collision detection would go in the same script file as when the player creates a bullet, maybe that can also go in Bullet.js

same with the entity check code

Still I have no idea what is the right way to use such a script in sphere, the bullet code is basically controlling a person on a map so I'm guessing I might as well all just throw it in a mapengine or update script or both but

Code: (javascript) [Select]

function Update()
{
  // your update script stuff
  UpdateBullets();
}

function game() {
    // your game code

    SetUpdateScript("Update()");
    MapEngine("map.rmp", 60);
}


by your update stuff you meant bullet update code stuff or just general update stuff?
same with game code?

I think If yes I would make a MapEngine.js and throw the entire code in there then have the function Update() to handle the rest of the code inside. I would call RequireScript(MapEngine.js) in the Startscript.js but how do I set it as a MapEngine script... I think if I can understand where and how to manage script files in Sphere I could be on my way to trying out this code and making my own for other stuff very smoothly. For now its an enigma.
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 07, 2013, 05:37:37 pm
I'll make a test demo, complete with all the resources and upload it here. Just wait it'll take a day to do.

Okay, I attached a demo project for you to learn from. :)
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 08, 2013, 02:54:35 am
 8) Your the man!

Title: Re: Shooting and Collision Detection
Post by: Xenso on July 08, 2013, 06:15:25 am
Noticed this

Code: (javascript) [Select]

var mw = GetLayerWidth(0) * GetTileWidth();
var mh = GetLayerHeight(0) * GetTileHeight();


Whats going on here?

Code: (javascript) [Select]

while (AreKeysLeft())
{
if (GetKey() == KEY_SPACE) CreateBullet("player");
}


What function can I use to check only if the player has pressed the key down. I want it so that even if the space-bar is held continuously only one bullet is fired.
Title: Re: Shooting and Collision Detection
Post by: DaVince on July 08, 2013, 06:31:14 am

Noticed this

Code: (javascript) [Select]

var mw = GetLayerWidth(0) * GetTileWidth();
var mh = GetLayerHeight(0) * GetTileHeight();


Whats going on here?

I haven't checked the script, but that gets you the size of the map in pixels. GetLayerWidth() and GetLayerHeight() get the size of a layer in tiles (assuming all layers are the same size here), so it has to be multiplied with the tile size itself.
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 08, 2013, 08:49:07 am
That makes sense now.

I found the functoin  isKeyPressed(); in the API Functions list ( Sphere Wiki ), Is there an isKeyReleased function?
I was thinking of making a variable to assign itself to != isKeyPressed(); but I have a big feeling that's going overboard and will not work.
The variable will be too big and I think this would kill computer memory.

Is there a way to limit the shooting to one shot per button press? I replaced the while loop with this code but it made the shooting more like a flame-thrower than what I wanted. ( hmm I'll keep that in mind maybe for a power up  :P )

Code: (javascript) [Select]

//If the player presses space
if (IsKeyPressed(KEY_SPACE)){ CreateBullet("Player")}
Title: Re: Shooting and Collision Detection
Post by: Fat Cerberus on July 08, 2013, 12:29:53 pm

I was thinking of making a variable to assign itself to != isKeyPressed(); but I have a big feeling that's going overboard and will not work.
The variable will be too big and I think this would kill computer memory.


Wh... why would it be too big? A boolean variable takes up a couple bytes in memory, you have billions of bytes to work with... ???
Title: Re: Shooting and Collision Detection
Post by: Radnen on July 08, 2013, 01:49:10 pm
Assigning a variable in a loop, just assigns the same data location over and over, it doesn't add more to memory. If computers were implemented that way we'd still be in the technological stone age! :P

To hit a key only once per click, the easiest way to do that is like this:
Code: [Select]

var key_hit = false;

function Update()
{
    if (IsKeyPressed(KEY_CTRL) && !key_hit)
    {
        do_something();
        key_hit = true;
    }
    if (!IsKeyPressed(KEY_CTRL)) key_hit = false;
}
Title: Re: Shooting and Collision Detection
Post by: Xenso on July 09, 2013, 06:59:13 am
Code: (javascript) [Select]
var key_hit = false;

function Update()
{
UpdateBullets();
if (!IsKeyPressed(KEY_Z)) key_hit = false;

if (IsKeyPressed(KEY_Z) && key_hit == false)
{
key_hit = true;
CreateBullet("ghost");
}


The code works perfect now. Thanks to all your help.  ;D