Shoot Bullets to player coordinate

Post here for help and support regarding LunaLua and SMBX2's libraries and features.

Moderator: Userbase Moderators

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Sat Sep 14, 2019 9:53 pm

As the title said... I want the code:

Code: Select all

local npc = NPC.spawn(arguments)
npc.speedX = a
npc.speedY = a
to shoot at player position/coordinate... I got these function:

Code: Select all

function point_direction(x1, y1, x2, y2)
	local angle = math.deg(math.atan2(x2 - x1, y2 - y1))
	
	if(angle < 0) then
        angle = angle + 360
    end

    return angle
end

function point_distance(x1, y1, x2, y2)
	return math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
end

function getAngle(vx, vy)
    return math.deg(math.atan2(vy, vx));
end

function getVelocityWithAngle(vx, vy) --Work like Pythagoras
    return math.sqrt(math.pow(vx, 2) + math.pow(vy, 2));
end
But I don't know how to implement this... Can someone help?

P/s: Does anyone know how to get block below custom NPC or check 2 block to the left is empty?

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Sun Sep 15, 2019 7:22 am

You might have to invert the vector in the code below... I always mix up the operands of the subtraction.

This goes to after you spawned the new NPC. Replace invalid variable names with your proper names:
--------------------------------------------------------
local speed = 5
local distanceBetweenPlayerAndNPC = vector(player.x - npc.x, player.y - npc.y)
local distNormal = distanceBetweenPlayerAndNPC:normalize()
--can also derive speed from distance
--speed = distanceBetweenPlayerAndNPC.length * 0.01
newNPC.speedX = distNormal.x * speed
newNPC.speedY = distNormal.y * speed
--------------------------------------------------------

Documentation is here:
https://wohlsoft.ru/pgewiki/VectR.lua
In the PAL version, the vector class is automatically loaded like in the example above. the vector(a,b) constructor automatically interprets the vector's dimension. Like you can see on the documentation page, it's also possible to rotate vectors, which could be useful if you want to make some sort of spread shot (projectile 1 misses by -5 degrees, projectile 3 misses by +5 degrees)


P/s:
A tad tricky, considering the ability for blocks to be nonsolid or invisible. You basically have to run a getIntersecting check on the desired coordinates and then filter the results by anything the NPC might be able to pass through regardless of its status as a block. The two checks you're asking for is just the same check again then, but offset by a certain amount:

This goes to where you need to do your check:
--------------------------------------------------------
local hasHitValidBlock = false
for k,v in ipairs(Block.getIntersecting(leftEdge, topEdge, rightEdge, bottomEdge) do
if (not v.isHidden) and v:mem(0x5C, FIELD_WORD) == 0 and (not Block.NONSOLID_MAP[v.id]) then
hasHitValidBlock = true
break
end
end
if (hasHitValidBlock) then
--execute code that depends on the npc finding a solid block. invert the conditional if you require the npc to find a lack of blocks for this code to run
end
--------------------------------------------------------
Docs: https://wohlsoft.ru/pgewiki/Block_(class)

The snippit assumes the PAL version, too. If you're on Beta 3, you'll need to load expandedDefines [[ local expandedDefines = API.load("expandedDefines") ]] and use expandedDefines.BLOCK_NONSOLID_MAP instead. The expandedDefines library is also where you're able to take a look at any block and npc lists I haven't listed in this post.

To get the block the NPC is standing on, you can store "v" in hasHitValidBlock, rather than true. That'll get you the first valid block you found. One thing to keep in mind: If the object you're checking on is standing on a top-solid NPC you might have to do the same checks for a NPC.getIntersecting check, checking for NPC.config[npc.id].playerblocktop and NPC.config[npc.id].npcblocktop.
Here's the docs for those:
https://docs.google.com/spreadsheets/d/ ... edit#gid=0
https://wohlsoft.ru/pgewiki/NPC_(class)

If you need to account for blocks that the NPC might be in FRONT of, the check gets a bit more complicated. the SEMISOLID_MAP includes top-solid and sizeable blocks and blocks you find from it should only be valid in your check if [[ block.y >= npc.y + npc.height ]] to ensure that the block's top bound is below the NPC's feet.

Hope this helps.

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Sun Sep 15, 2019 9:36 am

LOL I spend my whole day try to implement the GameMaker Studio style because I'm used it for too long... Thank boi :3

Edit: Another question to avoid double post... (Non-related question)

I notice that if I set speedX and speedY to an x value... With 8 bullets and changing the coding:

Code: Select all

local ball1 = NPC.spawn(arguments)
ball1.speedX = 8

local ball3 = NPC.spawn(arguments)
ball3.speedY = 8

local ball5 = NPC.spawn(arguments)
ball5.speedX = 8
ball5.speedY = 8

local ball7 = NPC.spawn(arguments)
ball7.speedX = -8
ball7.speedY = -8
Something like that... I noticed that it create a square box...

Now how can I make that "square box" into a circle... Or make 8 (or MORE ex: 20) spawned bullet form a nice circle

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Sun Sep 15, 2019 11:21 am

You can spawn them in a for loop. Think something like this:

local directionVector = vector(0, 8) -- down at speed 8
local lim = 20 --number of bullets

for i=1, lim do
local n = NPC.spawn(arguments)
n.speedX = directionVector.x
n.speedY = directionVector.y
directionVector = directionVector:rotate(360/lim) --rotate speed for next bullet by an amount that makes it so all bullets are evenly spaced
end

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Sun Sep 15, 2019 6:58 pm

Ok thank alot... I will keep this topic for 2 purpose... Ask again and/or let's others watch to fulfill their dream... SMBX 2.0 Engine has a lot of potential... :3

Added in 7 hours 47 minutes 28 seconds:
I made a boss based on a Cursor... It went perfect but I notice that the cursor is a single-life NPC... If I kill it, the event will be cancelled but the score still updated... I put the Cursor's score to 0 but it do nothing and return 10 score (ofc)... How can I remove the score? Is there anyway?

Edit: Nvm... You don't see the message above... Look away pls

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Mon Sep 16, 2019 6:37 am

You can cancel in onNPCHarm instead of onNPCKill. It runs slightly earlier, before sound and score are processed internally. Our docs are a bit of a mess right now so you can't find it very easily, sadly. Here's a little overview:
function onNPCHarm(eventObj, harmedNPC, harmReason, culprit)
The only new thing is the culprit, which can be nil, an NPC, a block, or a player. After typecasting the object (type(culprit), I think. Else, culprit.__type) in a conditional, you can figure out exactly what is responsible for the harm. Not perhaps necessary for your boss, but good to have around.

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Mon Sep 16, 2019 8:29 am

A super dumb question pls....? Can I draw a line/graphic/background animation in Lua? In GameMaker studio, there is Draw event... How about Lua... Does SMBX 2.0 Engine contain this or I must use some API?

For example... Can I draw a line and rotate it or cursor and rotate the "finger" of cursor/hand?

P/s: I got a bullet with static limited lifespan (130 tick = 2 sec). How can I spawn THAT bullet but with other lifespan (5 sec)

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Mon Sep 16, 2019 10:32 am

ItsRealGaming[R] wrote:
Mon Sep 16, 2019 8:29 am
A super dumb question pls....? Can I draw a line/graphic/background animation in Lua? In GameMaker studio, there is Draw event... How about Lua... Does SMBX 2.0 Engine contain this or I must use some API?

For example... Can I draw a line and rotate it or cursor and rotate the "finger" of cursor/hand?

P/s: I got a bullet with static limited lifespan (130 tick = 2 sec). How can I spawn THAT bullet but with other lifespan (5 sec)
Yes. There's a lot of different ways to draw things. The simplest way is with the Graphics.drawImage family of functions, which simply draws a defined subset of a sprite loaded through Graphics.loadImage[docs]. For more advanced drawing (stretch, squash, rotating), the Sprite class (loaded by default) works as a wrapper over the basic Graphics.glDraw{} function [docs] to make it easier to use [vid, docs within sprite.lua in smbx/data/scripts/base]. With all methods, animation is done by changing the subset of the image to draw. The sourceX and sourceY variables from drawImage's functions for example serve as a way to define the top/left corner of the spritesheet where drawing should begin, while the width and height arguments define the dimensions of that subset (in pixels). If you work with glDraw directly, the textureCoordinates are used to limit the drawn section instead and are within a 0-1 range (0 = top or left, 1 = bottom or right of the sheet). I forget what sprite.lua does, but I believe it's more akin to the way drawImage handles it.


P/s: Make the lifespan variable instead of static. If you don't wanna get into pnpc [vid, docs], you can store the variable in the NPC's ai5 variable. That one's least often used by Redigit's code. You can put in a number and manually count down to 0 and then manually kill the NPC with npc:kill(harmtype/killreason)

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Mon Sep 16, 2019 6:51 pm

Awesome... Now... This may not be involve to Vector but how can I check for player input without messed up with others... You know the 7 Koopaling boss? I want to make a combo input attack like that... That look so cool...

All I got is this:

Code: Select all

local disableInput = false

function onKeyDown(keycode)
	if player.runKeyPressing and player.upKeyPressing and not player.altRunKeyPressing and disableInput == false then
		local vegetable = NPC.spawn(147, player.x, player.y, player.section)
		vegetable.speedY = -8
		vegetable.speedX = -4
		disableInput = true
	end
	
	if player.runKeyPressing and player.altJumpKeyPressing and disableInput == false then
		Misc.dialog("LOL")
		
		disableInput = true
	end
end

function onKeyUp(keycode)
	if not player.runKeyPressing or not player.upKeyPressing then
		disableInput = false
	end
	
	if not player.runKeyPressing or not player.altJumpKeyPressing then
		disableInput = false
	end
end

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Mon Sep 16, 2019 7:24 pm

Not too sure about the boss... but I think I get the gist of what you're trying to do?
Instead of onKeyDown and onKeyUp, I recommend listening for changes in player.keys in onTick, and manually setting them if you wanna disable an input:
Available keys are: player.keys.down/up/left/right/run/altRun/jump/altJump/dropItem/pause
The fields are a four-way boolean:
When not pressed, the field is KEYS_UP (evaluates to false in a conditional)
When pressed for the first frame, the field is KEYS_PRESSED (evaluates to true)
When held for multiple frames, the field is KEYS_DOWN (evaluates to true)
When released this frame, the field is KEYS_UNPRESSED (evaluates to false)

So to disable jumping, you can just set:
player.keys.jump = KEYS_UP
And when listening to multiple inputs you can do:
if player.keys.up and player.keys.down then

end
If you want the combo to have a specific order you gotta do a bit more variable juggling I think. What might be good is using a table like so:
local combo = {
"up",
"down",
"right"
}
local comboTimer = 0
local comboProgress = 1
function onTick()
if comboProgress <= #combo then
if player.keys[combo[comboProgress]] then
comboTimer = 12
comboProgress = comboProgress + 1
end
else
--execute combo code and reset progress. maybe have a cooldown.
end
comboTimer = comboTimer - 1
if comboTimer == 0 then
comboProgress = 0
end
end

Hoeloe
Foo
Foo
Posts: 1465
Joined: Sat Oct 03, 2015 6:18 pm
Flair: The Codehaus Girl
Pronouns: she/her

Re: Shoot Bullets to player coordinate

Postby Hoeloe » Mon Sep 16, 2019 9:24 pm

Enjl wrote:
Mon Sep 16, 2019 7:24 pm

So to disable jumping, you can just set:
player.keys.jump = KEYS_UP
You can do this just like you would with the KeysPressing fields, and I'd suggest you do.

player.keys.jump = false

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Tue Sep 17, 2019 1:46 am

Awesome... One more thing... How can I check player get hurt (powerstate 1)? I got the code:

Code: Select all

local playerHealth = 5
if playerHealth >= 2 then
			if player.powerup == 1 then
				player.powerup = 2
			end
		else
			player.powerup = 1
		end
But it keep "squash" the player down...

P/s: My combo code:

Code: Select all

if comboProgress <= #combo then
		if player.keys[combo[comboProgress]] then
		comboTimer = 12
		comboProgress = comboProgress + 1
		end
	else
		local Hammer = NPC.spawn(171, player.x, player.y, player.section)
		Hammer.speedY = -7
		Hammer.speedX = -5
		comboProgress = 0
		comboTimer = 0
	end
	
	comboTimer = comboTimer - 1
	if comboTimer == 0 then
		comboProgress = 0
	end
is having a problem... ffi_player.lua:532: attemp to perform arithmetic on local "offset" (a nil value)... I believe this is not a problem of my code...

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Tue Sep 17, 2019 4:41 am

The way to check for changes in the player's state is by observing player.forcedState and player.forcedTimer (or is it forcedStateTimer? try the latter if the former is nil). They're documented as offsets 0x122 and 0x124 here, but we got fields for them since: https://wohlsoft.ru/pgewiki/SMBX_Player_Offsets

So if you detect forcedState to be 2, you can set it back to 0, set the timer to 0 and apply your powerup state back. The alternative solution (if you wanna keep the flicker animation) is to store the previous frame's forcedState and use a conditional to check a scenario where forcedState is 0 and previousForcedState is 2. Then you know the animation is over. I recommend onTickEnd for these ideas cause they happen just after SMBX's code every frame, while onTick happens just before. So you get the benefit of drawing the correct player state on frame 1 of the animation being over.

During the powerdown animation, it actually flickers between powerup states 2 and 1, which is why you see the squashing. You repeatedly apply the full-size hitbox and then SMBX tries to set state 2, adjusting the player y coordinate based on the assumption that they're currently in powerup state 1. The opposite happens when you try to apply powerup state 1, with SMBX trying to adjust the hitbox downwards since it assumes the player is big.

P/s:
It was actually a problem with my code... I set comboProgress to 0, but it should never be that, because the table entries for a combo start at 1. So it was trying to access player.keys[nil], which, of course, is invalid. Make sure comboProgress is never outside the range of the combo table.

Tip for the future: There's usually a stacktrace with the error message. By following that to the bottom and finding the first instance of your file, you can find out which line is responsible for the error on your end.

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Wed Sep 18, 2019 4:30 am

How do I detect player pickup Mushroom, Flowers, Hammer Suit, Tanooki... I don't want to check for box around player... Sure this may be the only way but is there any easier way?

P/s: Does this health code ok:

Code: Select all

function onTickEnd()
	if playerHealth >= 2 then
		if player.forcedState == 2 then
			player.forcedState = 1
			playerHealth = playerHealth - 1
		end
	end
	
	if (player.forcedState == 1 or player.forcedState == 4 or player.forcedState == 5 or player.forcedState == 11 or player.forcedState == 12) and player.forcedTimer >= 54 then
		playerHealth = playerHealth + 1
	end
end

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Wed Sep 18, 2019 3:10 pm

To detect powerup pickup, you can once again use forcedState. The docs I linked earlier have information for which value corresponds to which pickup.

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Thu Sep 19, 2019 5:50 am

I'm afraid this isn't goint to work when player is already "Big"... But no problem, I got a work around with this... Thank :3

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Thu Sep 19, 2019 6:51 am

Ah, that kind of collection. In that case, you can use load npcManager with require and use npcManager.collected(npc, killReason) in onNPCKill with the HARM_TYPE_OFFSCREEN killReason. That function covers stuff like overlaps, slashing, yoshi tongue, etc... and returns the player that would have collected the npc, if any (nil otherwise).

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Thu Sep 19, 2019 8:14 am

Perfecto... I want to recreate some enemies, but I seem to have a problem with v.direction (frameStyle = 1)...

Code: Select all

if actionTimer == 0 then
		if v.direction == -1 then
			spawnAtDirection(753, v.x, v.y, 3, 180)
		end
		
		if v.direction == 1 then
			spawnAtDirection(753, v.x, v.y, 3, 0)
		end
	end
Don't mind the spawnAtDirection function... That's just my vector-direction function...

The code seem simple, right? But the problem is the enemy with direction of -1 (left) is able to execute the code... Not the one with direction of 1

I made a debug: Text.print(v.direction, v.x - cam.x, v.y - cam.y) and I check for right direction value...

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9860
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: Shoot Bullets to player coordinate

Postby Emral » Thu Sep 19, 2019 8:19 am

Hmm... there seems to be more going on here. Can you share more code? You can post it to https://hastebin.com/ if it gets too long. The code formatting on that site works, too ;p
Particuarly interesting I think would be the remaining code for the current NPC and NPC 753, and just for good measure the spawnAtDirection function too.

ItsRealGaming[R]
Koopa
Koopa
Posts: 15
Joined: Sat Sep 14, 2019 9:00 am
Flair: R

Re: Shoot Bullets to player coordinate

Postby ItsRealGaming[R] » Thu Sep 19, 2019 8:23 am

Here: https://hastebin.com/zayehagige.sql

The NPC 753 is just a cannonball with nogravity... It work perfectly... Thank god that hastebin formatting is work

Btw the angle is based on GameMaker system ;3
Btw(2) I'm suck at animating... This code is based on the "Beck" enemies of Megaman 1... :3... The sprite only have 8 30x32 part (left/right)... I'm want to make animation with only 4 frames too :3

P/s: My hastebin link .sql sound like a Skill in a video game lol
Last edited by ItsRealGaming[R] on Thu Sep 19, 2019 9:46 am, edited 3 times in total.


Return to “LunaLua Help”

Who is online

Users browsing this forum: Superiorstar, Wonolf and 1 guest

SMWCentralTalkhausMario Fan Games GalaxyKafukaMarioWikiSMBXEquipoEstelari