Draw_sprite_part problem...

A

AFD456

Guest
Hello everyone, I have 3 object in my game: Plane (oPlane), bullet (oBullet) and tube (oTube).

What I want to code is following... When I shoot a bullet out of the plane and the bullet meets with the tube I want to show only a part of the tube. And it kinda works, until when I move the plane (right or left) then the revealed part of the tube changes according to position of the plane. In other words It moves along with the plane. Which doesnt make sense to me. Here's the code:

oPlane
Create Event:
globalvar can_shoot;
can_shoot = true

Alarm Event for alarm 0:
can_shoot = true

Step Event:
if keyboard_check_pressed(vk_space)
{
if can_shoot == true
{
can_shoot = false
instance_create(x,y,oBullet)
oBullet.vspeed = -8
alarm[0] = 10
}
}
// movement control
if keyboard_check(vk_left)
{
if x > 10
{
x -= 10
}
}
if keyboard_check(vk_right)
{
if x < room_width-40
{
x += 10
}
}

oTube
Create Event:
globalvar hit, touch;
//hit = false
touch = noone

Step Event:
if (place_meeting(x,y,oBullet))
{
touch = place_meeting(x,y,oBullet)
with(oBullet)
{
instance_destroy()
}
}

Draw Event:
if touch != noone
{
draw_sprite_part(sprite_index, 0, touch.x, 0, 50, sprite_height, touch.x-25, y);
}

Thank you for your time and answers.
 

Nallebeorn

Member
Well, for starters, place_meeting() doesn't return the colliding instance id, it just returns a bool (true or false). You'll want to use instance_place() instead. They take the same arguments, so you can just replace it, although there's some room for simplifying things to something like this, if you want:
Code:
touch = instance_place(x, y, oBullet);
with (touch)
{
    instance_destroy();
}
Additionally, remember that the left and top arguments of draw_sprite_part() should be the local coordinates within the sprite (i.e. 0,0 is the top-left corner of the sprite), not room coordinates. Are you sure touch.x shouldn't be touch.x - x?
 
A

AFD456

Guest
Well, for starters, place_meeting() doesn't return the colliding instance id, it just returns a bool (true or false). You'll want to use instance_place() instead. They take the same arguments, so you can just replace it, although there's some room for simplifying things to something like this, if you want:
Code:
touch = instance_place(x, y, oBullet);
with (touch)
{
    instance_destroy();
}
Additionally, remember that the left and top arguments of draw_sprite_part() should be the local coordinates within the sprite (i.e. 0,0 is the top-left corner of the sprite), not room coordinates. Are you sure touch.x shouldn't be touch.x - x?
First thank you for replying me!
Yes I understand that left and top arguments are local coordinates. I chose touch.x -25 because I want the revealed part to range from 25 on the left to 25 on the right from "place meeting" . Instance_place doesnt work. It gives me error.
100003 should be object index for oBullet. I checked it out
with(all)
{
draw_text(x,y, string(id))
}
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object oTube:

Unable to find any instance for object index '100003' name '<undefined>'
at gml_Object_oTube_DrawEvent_1 (line 4) - draw_sprite_part(sprite_index, 0,touch.x, 0, 50, sprite_height,0, y);
############################################################################################
 

Nallebeorn

Member
Oh.. Yes, yes, of course. You're deleting oBullet immediately after the instance_place(), so when trying to access it in the draw event, it no longer exists :p. You'll need to get and store the bullet's x position in the step event, so you can still use it in Draw even when the object is gone.

Step event:
Code:
var touch = instance_place(x, y, oBullet);
if (touch != noone)
{
    touch_x = touch.x;
    with (touch) instance_destroy();
}
Of course, you'll also need to initialize touch_x in the Create event to -1 or something, and then replace the if-check in Draw with if (touch_x != -1). There's also need to do globalvar touch, since it's only used (and only usable!) in the Step event of oTube. I'm not sure why you made it a global variable in the first place, though, unless you needed to access it from other objects...?
(On a side note, it's recommended not to use globalvar for global variables either way – it's deprecated, as written in the manual here. Instead, use the global. prefix.)
 
A

AFD456

Guest
Oh.. Yes, yes, of course. You're deleting oBullet immediately after the instance_place(), so when trying to access it in the draw event, it no longer exists :p. You'll need to get and store the bullet's x position in the step event, so you can still use it in Draw even when the object is gone.

Step event:
Code:
var touch = instance_place(x, y, oBullet);
if (touch != noone)
{
    touch_x = touch.x;
    with (touch) instance_destroy();
}
Of course, you'll also need to initialize touch_x in the Create event to -1 or something, and then replace the if-check in Draw with if (touch_x != -1). There's also need to do globalvar touch, since it's only used (and only usable!) in the Step event of oTube. I'm not sure why you made it a global variable in the first place, though, unless you needed to access it from other objects...?
(On a side note, it's recommended not to use globalvar for global variables either way – it's deprecated, as written in the manual here. Instead, use the global. prefix.)
We are getting closer !:)

Step event

touch = instance_place(x, y, oBullet);
if (touch != noone)
{
touch_x = touch.x;
with (touch) instance_destroy();
}
In Draw event I have to use if touch != noone because touch_x != noone gives me error even though I initialize it in Create event the same as touch variable:)

Create event

var touch_x, touch;

touch_x = noone
touch = noone

Error:
FATAL ERROR in
action number 1
of Draw Event for object oTube:
Variable oTube.touch_x(100003, -2147483648) not set before reading it.
at gml_Object_oTube_DrawEvent_1 (line 2) - if (touch_x != noone)

Otherwise it works but the part of tube which collides with bullet appears just for short time like for 1 second or not even that. Btw If it helps you I can upload this project.
 

Nallebeorn

Member
var is used to create a local variable, i.e. one that is only valid in the event (or script resource) where it was declared. To create an instance variable, i.e. one that is valid for only one instance, but in all its events, you don't need to use any specific keyword, you just assign to it. Replace your Create event with simply:
Code:
touch_x = noone;
And then you should be able to use if (touch_x != noone). The tube disappears almost immediately when you check for touch != noone, because that means the code will only execute during the step in which there was a collision with oBullet.
Also, you shouldn't initialize touch in Create. It's only needed in the Step event, which is why I used var there to make it a local variable.

P.S: You might want to read up on local, instance and global variables. It's all right there in the manual =)
 
A

AFD456

Guest
var is used to create a local variable, i.e. one that is only valid in the event (or script resource) where it was declared. To create an instance variable, i.e. one that is valid for only one instance, but in all its events, you don't need to use any specific keyword, you just assign to it. Replace your Create event with simply:
Code:
touch_x = noone;
And then you should be able to use if (touch_x != noone). The tube disappears almost immediately when you check for touch != noone, because that means the code will only execute during the step in which there was a collision with oBullet.
Also, you shouldn't initialize touch in Create. It's only needed in the Step event, which is why I used var there to make it a local variable.

P.S: You might want to read up on local, instance and global variables. It's all right there in the manual =)
I gotta check it out. Anyway thank you it works great! You made my day:)
 
Top