I'm developing a minigame where you can use the {MOUSE} to fire at enemies and destroy them with a simple click, similar to that minigame in Mario paint where you swatted flies. Since this is my first experience with manipulating the mouse, here's a short run of what I've got, and where things break down.
A brief technical demonstration of what's going on. Enemies rush at you with deadly weapons, who'll kill you in one hit and send you back to the start of the level/nearest safe point. You use the mouse to shoot and kill them before they can touch you. Simple and easy, right?
script, mouse script, begin
# Must be called before any other mouse command
init mouse
variable (avoid warning) # Kludge to suppress the "infinite loop" compiler warning
avoid warning := true
# Infinite loop, yes, there's a reason
while (avoid warning) do, begin
# You can put an appropriate condition here, or "true" (or "avoid warning" to avoid the warning)
if (tag:Mouse active) then, begin
# In the next line, change the "0" to the ID of the mouse NPC
put NPC (0, mouse pixel x + camera pixel x, mouse pixel y + camera pixel y)
if (mouse button(left button)) then, begin
variable (NPC, Num NPC, i)
num NPC := NPC at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, 1)
for (i,0,Num NPC -- 1,1) do, begin
NPC := npc at pixel(mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, i)
if(get NPC ID(NPC) == 8) then, begin
FOE8
end
if(get NPC ID(NPC) == 9) then, begin
FOE9
end
if(get NPC ID(NPC) == 10) then, begin
FOE10
end
end
# Check what's been clicked
end
end
# Let game.exe breathe
wait
end
end
NPC 0 has a little crosshairs to lock onto any foe on screen, and if the script is working, it'll recognize which NPC is being targeted, then run a smaller script to determine what to do with it...
script,FOE8,begin
suspend NPCs #I don't really want anything moving around for a second
tweak palette (40,-10,-10)
update palette
play sound (sfx:Slash8Bit,false,true)
wait (1)
reset palette
update palette #All this is to basically make the screen flash
Alter NPC (8,NPCstat:picture,14)
wait (1)#the NPC VERY briefly changes its sprite to explode
set tag (tag:FOE8,on)#And this tag kills the NPC
resume NPCs
end
The script is doing one of two things, which I'm not positive I understand what's going on. Either the NPC crosshairs is not lining up at all with the desired NPCs to trigger the proper script.... ...OR, there's an error in each NPC script that somehow is preventing them from running. I'd much rather not even bother with the ACCURACY of whether the mouse's crosshairs are exactly lined up with the NPC "enemy", so long as it's on the same tile It also has to be specific as to what NPC is being targeted, since there are "friendlies" also on each map who you don't want exploding for no apparent reason.
To friends long gone, and those I've yet to meet - thank you.
for (i, 8, 10) do, begin #NPC ids 8-10
for (j, 0, npc copy count(i)) do, begin
ref := npc reference(i, j) # Get the Jth copy of npc I
if (npc pixel x(ref) -- npc pixel x(0) << 10 &&
npc pixel x(0) -- npc pixel x(ref) << 10 &&
npc pixel y(ref) -- npc pixel y(0) << 10 &&
npc pixel y(0) -- npc pixel y(ref) << 10) then, begin
kill npc (ref) # kill off the one we found
end
end
end
And replace kill npc(ref) with whatever it is you want to do with them. The problem, I think, is that npc at pixel does not really work like you want it to. The code above will detect any NPCs that are within the hitbox of the crosshairs. You can increase or decrease the 10s to adjust the precision needed.
for (i, 8, 10) do, begin #NPC ids 8-10
for (j, 0, npc copy count(i)) do, begin
ref := npc reference(i, j) # Get the Jth copy of npc I
if (npc pixel x(ref) -- npc pixel x(0) << 10 &&
npc pixel x(0) -- npc pixel x(ref) << 10 &&
npc pixel y(ref) -- npc pixel y(0) << 10 &&
npc pixel y(0) -- npc pixel y(ref) << 10) then, begin
kill npc (ref) # kill off the one we found
end
end
end
And replace kill npc(ref) with whatever it is you want to do with them. The problem, I think, is that npc at pixel does not really work like you want it to. The code above will detect any NPCs that are within the hitbox of the crosshairs. You can increase or decrease the 10s to adjust the precision needed.
Let me know if this needs more explaining.
This was the first thing that went through my head reading this. To be frank, there's a reason my games focus almost entirely on graphics, rather than scripting. Last month's Hamsterspeak "comic" using the endless loop of two backdrops is literally the most complex scripting I've ever done.
The script I posted was essentially a cut-and-run copy from the official site. Somehow I'll have to figure out how to make it so it also recognize individual NPC "foes" so I can make some take more than one hit to kill. This was partly the reason I have it check each individual NPC, rather than use NPC references. Normal foes simply turn on a specific tag for each individual foe, whereas stronger enemies would add a temporary item to the inventory, then die after so many of those temporary items are aquired. I figure this is the easiest way to fake enemy health. If I could somehow or other dumb it down even further to only check by TILES instead of pixels, that would be tremendously more helpful. Anything to avoid using the default battle engine.
To friends long gone, and those I've yet to meet - thank you.
script, mouse script, begin
# Must be called before any other mouse command
init mouse
variable (avoid warning) # Kludge to suppress the "infinite loop" compiler warning
avoid warning := true
# Infinite loop, yes, there's a reason
while (avoid warning) do, begin
# You can put an appropriate condition here, or "true" (or "avoid warning" to avoid the warning)
if (tag:Mouse active) then, begin
# In the next line, change the "0" to the ID of the mouse NPC
put NPC (0, mouse pixel x + camera pixel x, mouse pixel y + camera pixel y)
if (mouse button(left button)) then, begin
# Check what's been clicked
for (i, 8, 10) do, begin #NPC ids 8-10
for (j, 0, npc copy count(i)) do, begin
ref := npc reference(i, j) # Get the Jth copy of npc I
if (npc pixel x(ref) -- npc pixel x(0) << 10 &&
npc pixel x(0) -- npc pixel x(ref) << 10 &&
npc pixel y(ref) -- npc pixel y(0) << 10 &&
npc pixel y(0) -- npc pixel y(ref) << 10) then, begin
kill npc (ref) # kill off the one we found
end
end
end
end
end
# Let game.exe breathe
wait
end
end
You might replace kill npc(ref) with FOE8, FOE9, and FOE10, based on your script.
script, KILLFOE, who, begin
suspend NPCs #I don't really want anything moving around for a second
tweak palette (40,-10,-10)
update palette
play sound (sfx:Slash8Bit,false,true)
wait (1)
reset palette
update palette #All this is to basically make the screen flash
Alter NPC (WHO, NPCstat:picture,14)
wait (1)#the NPC VERY briefly changes its sprite to explode
set tag (WHO, on)#And this tag kills the NPC
resume NPCs
end
For the sake of argument, every NPC does something radically and totally different. Otherwise, even bosses would die in a single hit, locked doors wouldn't function properly, etc.
WORKAROUND. Make the Target check TILE locations! Granted, it's now about as accurate as a Nintendo Zapper (tm), but checking NPC locations SHOULD theoretically be MUCH easier.
script, mouse script, begin
# Must be called before any other mouse command
init mouse
variable (avoid warning) # Kludge to suppress the "infinite loop" compiler warning
avoid warning := true
# Infinite loop, yes, there's a reason
while (avoid warning) do, begin
# You can put an appropriate condition here, or "true" (or "avoid warning" to avoid the warning)
if (tag:Mouse active) then, begin
# In the next line, change the "0" to the ID of the mouse NPC
set NPC Position (0, ((mouse pixel x + camera pixel x) /20) , ((mouse pixel y + camera pixel y) /20))
if (mouse button(left button)) then, begin
variable (NPC, Num NPC, i)
num NPC := NPC at spot ( ((mouse pixel x + camera pixel x) /20) , ((mouse pixel y + camera pixel y) /20), 1)
for (i,0,Num NPC -- 1,1) do, begin
NPC := npc at spot(((mouse pixel x + camera pixel x) /20), ((mouse pixel y + camera pixel y) /20), i)
if(get NPC ID(NPC) == 8) then, begin
FOE8
end
if(get NPC ID(NPC) == 9) then, begin
FOE9
end
if(get NPC ID(NPC) == 10) then, begin
FOE10
end
end
# Check what's been clicked
end
end
# Let game.exe breathe
wait
end
end
To friends long gone, and those I've yet to meet - thank you.
script, mouse script, begin
# Must be called before any other mouse command
init mouse
variable (avoid warning) # Kludge to suppress the "infinite loop" compiler warning
avoid warning := true
# Infinite loop, yes, there's a reason
while (avoid warning) do, begin
# You can put an appropriate condition here, or "true" (or "avoid warning" to avoid the warning)
if (tag:Mouse active) then, begin
# In the next line, change the "0" to the ID of the mouse NPC
set NPC Position (0, ((mouse pixel x + camera pixel x) /20) , ((mouse pixel y + camera pixel y) /20))
if (mouse button(left button)) then, begin
if ( ( (NPC X (0)) == (NPC X (8)) ) and ( (NPC Y (0)) == (NPC Y (8)) ) ) then, begin
FOE8
end
if ( ( (NPC X (0)) == (NPC X (9)) ) and ( (NPC Y (0)) == (NPC Y (9)) ) ) then, begin
FOE9
end
if ( ( (NPC X (0)) == (NPC X (10)) ) and ( (NPC Y (0)) == (NPC Y (10)) ) ) then, begin
FOE10
end
# Check what's been clicked
end
end
# Let game.exe breathe
wait
end
end
And there it is. TILE-based mouse movement, with a simple-to-understand series of steps to check for individual NPC placement, and run individualized scripts. Even a newbie should be able to reasonably tweak it, or use it in their own games, or even edit levels. Nice.
To friends long gone, and those I've yet to meet - thank you.