slice hitboxes, slice collision

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7658
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Virtuous Sword wrote:I don't mean to be funny, but do you intend to add some visual confirmation that an entry can be expanded? such as brackets or a '+' next to it, perhaps on the left?

edit: oh I see you put the number of child slices on the right, forgive me.... maybe something on the left e.g.'+' might be more visually immediate?
Yeah, that does look a bit better. I am changing it.

Image
How do layers relate to collisions?
Collision checking with "slice collide" tests if the slices overlap based on their screen positions-- so it doesn't really matter how they are parented, as long as they are displaying as overlapping.

layering does matter more for "find colliding slice", since it may or may not be checking child slices depending on how you call it, but the basic rule is still true, if the slices look like they are overlapping, then it will detect them as colliding.
What if I want to check for collisions with hero sprite slices or NPC sprite slices?
You can do that too. see the "get hero slice" and "get npc slice" commands.

If the enemies in your game are just regular NPCs then you would be best off using "next npc" to loop through each of them, and then use "get npc slice" to get the slice that you will be checking against your attack hitbox layer.
Currently, I'm making parenting a slice to a NPC, so that it's unaffected by screen movement.
You mean the attack hitboxes are parented to an NPC slice?

That can work, but makes checking for collision more work, because you have to loop through each NPC yourself and check its children.

I suggest creating a container to be your hitbox layer. Attach it to the same map layer that has heroes and NPCs on it, and set it to fill its parent. That will make the container exactly the same size as the map layer.

Then you can parent your hitboxes to the hitbox layer, and set their X,Y position based on the NPC pixel x and NPC pixel y of the npcs (which also happens to be the same as the slice x and slice y of an NPC's slice)

...actually, that method works well if your hit boxes are instantaneous and only stick around for one game tick. If they last longer than that, and you want them to move along with to the NPC they are attached to, then it is better to parent the hitboxes to the NPC, and just accept that you will need to write some more complicated collision checking.

Have you had any experience yet with looping over all NPCs in a script? Or with looping over all the child slices of a parent slice? If not, I can find you some examples.
Sorry for the questions, I'm not really good at coding/scripting.
No problem, you actually seem to be holding your own quite well :)
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

Thanks for clarifying how layers/collisions do.

I will try that looping through npcs thing. So far I'm having trouble even getting one hit to register! :p

To clarify, I meant attaching a slice representing an enemy to an npc. for the purposes of a hitbox smaller than a walkabout.
Is that an unnecessary step?
I'm still working out pixel movement, and trying to figure out if it'd be worth it to move to a slice-only type deal, or possibly abandoning that and sticking with tile based movement.
Drawing a hitbox smaller than a walkabout and parenting to an npc effectively makes it grid bound, no? I wish slices had behaviours :p well, I'm sure one can script a behaviour for a slice!
Using sizes smaller than a walkabout seems to require a lot of kerfuffling!
Maybe I am doing it wrong. I have ideas for a handful of different action games to be recreated in CUSTOM using slices, including point+click, mouse-based shooter, action-adventure dungeon crawler platformer thing... I got lots of ideas :p

It'd be good to be able to toggle views somehow (not just expandable lists, in many ways and in lots of ways across the editor... I know it's a lot of work though...)
Last edited by SwordPlay on Mon Mar 13, 2017 11:12 pm, edited 2 times in total.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

It's actually be possible to change the size of an npc container slice, but I don't think that will achieve anything useful, since you don't have control over its position unless you use putnpc (which will then break tile-based walking). But if you were planning on using scripted pixel-based movement, then it actually could work out well!

I think we should add a bit to slices to indicate whether they should be found by "find colliding slice". Then you could mark the walkabout container and sprite for an NPC as non-colliding, but still recursively descend to an invisible hitbox child of the NPC and detect a collision with that. This setting would be extremely useful for clickable slice-based menus. Already, the slice editor has special cases for which slices to ignore when you click on a slice.

(However, I don't know, if we do add such a bit, maybe it makes more sense for it to also block recursion to its children. That's how "find colliding slice" treats invisible slices, if visible only = true.)

Although, long-term whenever pixel-based movement is finally added, I was planning on just using the walkabout container of each NPC/hero as its hitbox.

Note, it's "next npc reference", not "next npc".

Sorry, did you have an unanswered question?
Mogri wrote:If you need lots of data on a slice, you can give it invisible children and use the parent extras to point to those children ("the TMC technique").
You're mistaken; that's James' signature technique. I still typically use arrays of globals!
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

I've decided to give up on collision detection for now, at least until I gain more familiarity with plotscripting.
I feel there are too many awkward factors in both tile and pixel based movement.
-walls in a pixel based system
-spawning and collision on moving objects in a tile based system, short of waiting for movement to stop
-is there a way to check if npcs are touching, short of comparing their x/y?
-can npcs be selectively passable to each other? something like that would be useful for slices too.

Thanks for the help and suggestions.
I had more ideas, each of which requires more plotscripting than the last.
Maybe in the future, a later release might add features that could ease the gap between engine and script.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Well, you might be right that this is too ambitious if you aren't comfortable enough with scripting.
-walls in a pixel based system
Wall checking can be done without too much trouble using the new "move slice with wallchecking" or "check wall collision x/y" commands.
However in practice if you're using pixel based movement including diagonal movement, I find that the movement doesn't feel right unless you can also slide along walls, and get automatically nudged to the side when you just hit the edge of an obstacle. And that still requires a bunch of scripting (though I want to add commands for that too).
-is there a way to check if npcs are touching, short of comparing their x/y?
No. But that's really easy, assuming they're 20x20:

Code: Select all

if&#40;abs&#40;npc pixel x&#40;npc1&#41; -- npc pixel x&#40;npc2&#41;&#41; <= 20 && abs&#40;npc pixel y&#40;npc1&#41; -- npc pixel y&#40;npc2&#41;&#41; <= 20&#41; then &#40;...&#41; 
But note: this actually checks for "touching or overlapping". Use slicecollide to distinguish the two. Or don't, if it's not possible for them to overlap anyway. Also, this counts meeting diagonally at one corner as touching.
-can npcs be selectively passable to each other? something like that would be useful for slices too.
The most fine-grained option available is to use "set npc obstructs(npc, false)", which makes an npc instance passable to all other NPCs.

As for slices, that's basically what I proposed in my last post.

Thinking more about it, I think there should be two new slice bits, one to ignore a slice and all its children, and another to ignore a slice but recurse to its children even if 'descend' if false, Two different use cases: one is for slices we plain don't care about, the other for invisible container slices which we want to treat as a collection of slices that do matter.
Last edited by TMC on Thu Mar 16, 2017 11:26 pm, edited 2 times in total.
User avatar
Gizmog
Metal King Slime
Posts: 2622
Joined: Tue Feb 19, 2008 5:41 am

Post by Gizmog »

TMC wrote:Wall checking can be done without too much trouble using the new "move slice with wallchecking" or "check wall collision x/y" commands..
Ho ho ho, Merry Christmas. When I get back into making games, that is going to be used and abused, my friend!
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

So, I managed to make this script thanks to your kind help.
However, it only seems to work when npcs are aligned just right?
When the target is moving, it doesn't seem to work reliably.
Any tips or suggestions?
I think even a glancing collision should be okay for my purposes, as long as the hit registers.

Code: Select all

plotscript, shoot, begin


if
&#40;key is pressed &#40;key&#58;z&#41;&#41;
then
&#40;
create NPC &#40;0, hero x&#40;me&#41;,  hero y&#40;me&#41;,hero direction&#40;me&#41;&#41;
set npc obstructs &#40;0, false&#41;
walk npc &#40;0, NPC direction&#40;0&#41;, 4&#41;

if
&#40;abs&#40;npc pixel x&#40;0&#41; -- npc pixel x&#40;1&#41;&#41; <= 20 
&& 
abs&#40;npc pixel y&#40;0&#41; -- npc pixel y&#40;1&#41;&#41; <= 20&#41; 
then 
&#40;destroy NPC&#40;1&#41;&#41; 

wait for NPC &#40;0&#41;
destroy NPC &#40;0&#41;
&#41;

end
I also tried using
slice collide (get npc slice(0), get npc slice(1))

but it seems to suffer similarly. Is there an advantage to one method or another?

I'm running as on-keypress.
Should I tie the collision script to the NPC?
Last edited by SwordPlay on Mon Mar 20, 2017 11:57 am, edited 2 times in total.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Ugh, it took me waaaaay too long to see the problem with your script: you only check for collision at the instant that you create the projectile, so it only works when you're standing next to them. (And also, although you have multiple copies of that NPCs, you're only checking one of them for collision) Try this instead:

Code: Select all

variable &#40;npc, idx&#41;
while&#40;npc is moving&#40;0&#41;&#41; do &#40;
  for &#40;idx, 0, npc copy count&#40;1&#41; -- 1&#41; do &#40;
    npc &#58;= npc reference&#40;1, idx&#41;   # the idx'th copy

    if &#40;abs&#40;npc pixel x&#40;0&#41; -- npc pixel x&#40;npc&#41;&#41; <= 20 &&
        abs&#40;npc pixel y&#40;0&#41; -- npc pixel y&#40;npc&#41;&#41; <= 20&#41;
    then &#40;destroy NPC&#40;npc&#41;&#41;
  &#41;
&#41;
"slice collide" and the manual position checking in this case are equivalent. The only difference is in how easy it is to adapt to other situations. For example, if your projectile isn't 20x20, then you should use slicecollide, because using abs isn't going to work.
Last edited by TMC on Mon Mar 20, 2017 11:54 am, edited 1 time in total.
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

ah cheers. I was wondering if I should put the collision script seperately for example as autorun or make it the npc's script or something.
I'm still having trouble understanding it tbh

What is idx? Gonna try this code presently. Thanks
"Imagination. Life is your creation."
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

Yaaay! works perfectly! thanks so much for your help!
I've finally got my first collision testing working!

btw, I think it's (while NPC is walking) not (while NPC is moving) as it seemed to give me an error?
I'm using the nightly build to take .gif screenshots. Super handy!


EDIT
I'm beginning to feel optimistic about making and submitting a game.
Even though it was only possible by reading everyone's advice and code very carefully, and even then, it seems I didn't understand it :(
Baby steps I guess
Last edited by SwordPlay on Mon Mar 20, 2017 12:12 pm, edited 1 time in total.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

If you want multiple projectiles on screen at once, then you're going to want to structure your scripts quite differently, and will want a separate script doing the collision checking rather than do that in the script that spawns the projectile.

"npc reference(1, i)" returns the i'th copy of npc ID 1. So i (or idx ("index") as I named it), loops up to the number of copies, in order to loop over them all. If your shootable NPCs have a range of different IDs, then it would be easier to instead loop over all NPCs (eg using "next npc reference") and check if you collided with them, and then decided whether to destroy it or not (eg by checking its ID). Or you could use "find colliding slice" instead.
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

I have to be honest, I'm not really sure on how to do that.
Would it be possible to change the npc using a script, such that all targetable npcs have the same ID, but different behaviour and picture based on their copy number?
That sounds stupid, but I honestly have no idea.

I just tried to copy the section you provided, and replaced the ID from 1 to 2 for the new NPC ID, but it broke collision with the first ID type. Does it need its own 'index' as well?
Where it is defined as a variable (NPC, idx) should it be duplicated for other NPC IDs?

I am literally just copying and pasting at this stage. Sorry. I hate to be a burden.
Looping through npcs seems to be quite fundamental. I am trying to learn this.

I sometimes get confused between handles, references, lookups and how to define them in a script.

Say I want to create a bullet being fired by an npc.
I would create a variable such as (bullet) then (guessing here), looping through the index, call (bullet:= create slice) for each copy of that npc, put slice (bullet) at that copies x/y, and then shoot it at the player?

Am I missing a step? Sorry, again. You are truly an angel for helping me out. I feel dimwitted :p

Maybe I need to take a step back here.
In the snippet you gave, how is variable(npc, idx) defined?
I see
npc:= npc reference
means that the variable npc will be read as "npc reference"


you also wrote
for
(idx, 0, npc copy count(1) -- 1)
which is basically the line I don't understand. (amongst other things!)
Does this define idx for the plotscript?
EDIT:
I may postpone this until I get more understanding. I think at this stage, trying to understand the correct logic for a script to follow is more important for me to learn.

For example, I often see you folks putting while()do() and nesting if()then() so that would imply I don't have a grasp of the syntax.
I think I should go away and do a few exercises before bothering you folks :p
I am also learning the plotscripting dictionary which is not difficult, but I am unable to wield the phrases together and connect them in a satisfactory manner, for example.


EDIT EDIT
I think I was looking for this

Code: Select all

for&#40;counter,start,finish,step&#41; do&#40;commands&#41;
EDIT EDIT EDIT
Okay, I see that the variable idx is a counter, with arguments
It loops through as many times as is between '0' and the number of NPC copies... --1?
So this will loop 'idx' number of times, and the loop it is presently running will be the 'idx'th number pointing at an npc with a copy number... equal to idx?
So this npc can be referred to by the number in the loop it corresponds to, which is its NPC copy count number. whew (?) still not sure why copy count "--1"

I was reading the plotscript dictionary, and it mentions that when using next npc ref, creating npcs might result in them being overlooked?
(I would like to create an npc that can spawn other npcs, for example.)

EDIT:
I realised that idx refers to one npc at a time. I have made progress! yaaay!
Thanks for teaching me!
Last edited by SwordPlay on Mon Mar 20, 2017 4:58 pm, edited 5 times in total.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Virtuous Sword wrote:Would it be possible to change the npc using a script, such that all targetable npcs have the same ID, but different behaviour and picture based on their copy number?
While it's possible to give two NPCs with the same ID different graphics (by using slice commands), they all have the same behaviour, you definitely want to use multiple NPC definitions/IDs instead.
I just tried to copy the section you provided, and replaced the ID from 1 to 2 for the new NPC ID, but it broke collision with the first ID type. Does it need its own 'index' as well?
So you worked this out? Are you using 'next npc reference' now to loop through NPCs?
I sometimes get confused between handles, references, lookups and how to define them in a script.
Sometimes commands aren't entirely explicit about which sort they take. But "lookup slice" is the only thing that takes a lookup code, all other slice commands use slice handles. All NPC commands can use either an NPC ID or an NPC reference.
For example, I often see you folks putting while()do() and nesting if()then() so that would imply I don't have a grasp of the syntax.
A script is not a linear list of commands. Think of it as composed of blocks of commands. Flow control like 'if' and 'for' controls the movement between the blocks. That's why it's extremely helpful to indent your scripts properly, so that you can tell apart the different blocks, and see where execution jumps to when you leave a 'then' block, for example.
It loops through as many times as is between '0' and the number of NPC copies... --1?
So this will loop 'idx' number of times, and the loop it is presently running will be the 'idx'th number pointing at an npc with a copy number... equal to idx?
So this npc can be referred to by the number in the loop it corresponds to, which is its NPC copy count number. whew (?) still not sure why copy count "--1"
The reason is that if you have 4 copies of an NPC, their copy numbers will be 0, 1, 2, 3. Everything in the OHR starts counting from 0 (with the unfortunate exception of positions inside a string), which means the last item is always one less than the number of items. If you wanted, you could instead write

Code: Select all

for &#40;idx, 1, npc copy count&#40;1&#41;&#41; do&#40;
  npc &#58;= npc reference&#40;1, idx -- 1&#41;

I was reading the plotscript dictionary, and it mentions that when using next npc ref, creating npcs might result in them being overlooked?
(I would like to create an npc that can spawn other npcs, for example.)
Hmm, yes. But I don't think it would really matter, because it just means there's a one tick delay before you process that NPC for collision detection or whatever.
What you could do to avoid the problem is loop over all NPCs twice: first handle the ones that shoot projectiles, and then handle the projectiles (collision checking).
User avatar
SwordPlay
Chemical Slime
Posts: 966
Joined: Sun Jan 22, 2017 9:32 am
Location: London, England
Contact:

Post by SwordPlay »

Code: Select all

I'm not sure what the advantage is to next npc ref over choosing which IDs to check against... I'm still learning &#58;p




What are the triggers for things to happen?
Something in autorun only runs once. What is a good way to make it continuously run?
What if I have more than 1 script I wish to autorun? Should I give them a common trigger such as 
while&#40;true&#41;
do&#40;code1&#41;
do&#40;code2&#41;
?
How can I make loops run in parallel? what about 'continue' and 'break? do they terminate the running loop?

How can I make a HUD update?
Should ir run in a loop and refresh itself, or should I tie a refresh command to every code that changes it?

How can I make an npc damage the player by chasing and touching the player?
It only seems to work if the player instigates the touch.
I want enemies to seek out and harm the player via touch.
I also want them to shoot bullets, but later on, perhaps
Is this a good idea?:


variable(target)

plotscript, collisions,
target:=next npc ref
## this gets the ID/copy of an NPC

while (target)
do (
if(slice collide)
then(damage script)
target:=next npc ref
)

script "damage"

set npc extra (target, 0, +1)
##npc extra is damage, it counts up

switch (get npc ID (target))
case 0 (npc id 0)
if (npc extra (target,0) >= 5)
then (destroy npc(target)
## if the npc (target) has id0 and has more than 5 points of damage, destroy it
case 1 (npc id 1) subscript enemy life
etc.
Last edited by SwordPlay on Tue Mar 21, 2017 7:43 am, edited 5 times in total.
"Imagination. Life is your creation."
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Virtuous Sword wrote:What are the triggers for things to happen?
Something in autorun only runs once. What is a good way to make it continuously run?
What if I have more than 1 script I wish to autorun? Should I give them a common trigger such as
while(true)
do(code1)
do(code2)
?
How can I make loops run in parallel? what about 'continue' and 'break? do they terminate the running loop?
'break' exits a while or for loop, 'continue' does not.

You can't have two while loops running at once, because the engine currently only allows one script to be active at once (something we badly need to implement!)

To get around this, either you can use timers (because then your script can exit and start again fresh the next time; it doesn't stay active so doesn't block anything else), or combine your while loops into a second loop. I recommend doing the later. For example:

Code: Select all

plotscript, main loop, begin
 while &#40;true&#41; do &#40;
   # Handle player input
   if &#40;key is pressed&#40;key&#58;esc&#41;&#41; then &#40;game over&#41;
   # Let he play shoot, etc

   # Make NPCs shoot at you
   handle npcs

   check for collisions

   update hud

   # etc...

   wait&#40;1&#41;
 &#41;
end
Basically, this main script calls various other scripts every tick
None of the scripts that are called from this script should contain wait commands.

To see a real example, I *highly* recommend you read the sidescroller 101 scripts, see http://rpg.hamsterrepublic.com/ohrrpgce ... lling_Game. You can learn a lot about scripting from these, and what you will learn from them will be quite relevant to other types of games.

Also, you can have a look at some of Giz's tech demos. In particular, the Tank tutorial is very similar to what you're working on (most of the others aren't relevant).
How can I make a HUD update?
Should ir run in a loop and refresh itself, or should I tie a refresh command to every code that changes it?
I suggest just updating the HUD every tick. Even if you delete the old slices and create new ones. It's just simpler to do it that way than to update it everywhere that you need to (eg when the player is hurt, when they use ammo, when they heal, etc).
You could create the HUD as a slice collection, put some lookup codes on slices like the HP amount text slice, load the collection, use "lookup slice" to find the slices that need changing, and change them (e.g with "set slice text")
How can I make an npc damage the player by chasing and touching the player?
It only seems to work if the player instigates the touch.
I want enemies to seek out and harm the player via touch.
I also want them to shoot bullets, but later on, perhaps
Touch-activated NPCs are meant to work when the NPC walks into the player too... but honestly, touch NPCs work strangely and badly. I wouldn't be surprised if they don't work well enough for you, so if you're making a shooter, scripting the touch-activation instead is a good idea so you can get it just how you want it. You can use the script I posted earlier with the "abs(...) <= 20" to check for touching, but this time compare npc and hero position, like "abs(hero pixel x(me) -- npc pixel x(npc)) <= 20) && ...". But this triggers a collision if you're touching just diagonally on a corner, which is maybe not what you want?

The pseudocode you wrote definitely looks like the right idea. (Aside from wrong syntax in various places, but I think you know that). I noticed you even mentioned a subscript at the bottom. So you're using subscripts?
Last edited by TMC on Tue Mar 21, 2017 11:44 am, edited 3 times in total.
Post Reply