RawDrawLine running in background (SOLVED)

Started by magintz, Tue 11/09/2007 17:37:25

Previous topic - Next topic

magintz

I'm trying to create a puzzle where a laser beam is moving about the screen, but I want the laser to be moving slowly in the background so the user can solve the puzzle before the laser hits them. I've got the movement down to a 'T'. But I need the user to be able to continue playing. Here's what I got for the movement:

Code: ags

ypos = 171;
while (ypos > 134) {
  RawRestoreScreen ();
  RawDrawLine(198,22,47,ypos);
  Wait(1);
  ypos--;
}


The other thing I need is for the line to draw itself above all the other objects in the room; the line currently shows up behind the objects.
When I was a little kid we had a sand box. It was a quicksand box. I was an only child... eventually.

GarageGothic

It's not possible to RawDraw in front of objects. What you can do is make the laser beam as a sprite, which is then copied to a DynamicSprite, stretched, rotated and placed in the room as an object.

magintz

Hmm, that might work :D I assume AGS has functions, which allow the stretching and manipulation of sprites?

Thanks Again,
Magintz
When I was a little kid we had a sand box. It was a quicksand box. I was an only child... eventually.

Ashen

In the manual: DynamicSprite functions and properties (particularly Resize, and probably CreateFromExistingSprite). Or, you could just import the sprites and run it as a standard animation - a bit of a waste of sprite slots, but if it's just a straight line it shouldn't take up much space.
I know what you're thinking ... Don't think that.

Khris

To run it in the background:

Code: ags
int ypos = 171;

function repeatedly_execute() {
  if (ypos > 134) {
    RawRestoreScreen ();
    RawDrawLine(198,22,47,ypos);
    ypos--;
  }
  else kill_player();
}


This code won't work as-is but should get you started.

monkey0506

#5
But that still doesn't solve the issue of making the laser appear in front of objects.

Instead of using DynamicSprite.Resize and DynamicSprite.Rotate every game loop (which the manual specifically says not to do) you could use a combination of the RawDraw functions, a DynamicSprite, and an object.

1. nvm

2. In your room's "on-load" function call RawSaveScreen and RawSetColor.

3. In your room script make a DynamicSprite* (I'll name it dsLaser). Also put your "int ypos = 171;" at the top of your room script.

4. Finally, in your room's repeatedly_execute function, put this:

Code: ags
if (ypos > 134) {
  RawClearScreen(63519);
  RawDrawLine(198, 22, 47, ypos);
  dsLaser = DynamicSprite.CreateFromBackground(GetBackgroundFrame(), 47, 22, 198 - 47, ypos - 22);
  RawRestoreScreen();
  oLaser.Graphic = dsLaser.Graphic;
  ypos--;
  }
else {
  // kill player
  }


The color 63519 is a "magic pink" color that will be drawn as transparent when used by your sprite. So I've cleared the screen out to that color, drawn the laser, and then grabbed the entire rectangular area of the laser into the DynamicSprite. Then you restore the screen back to normal and set the object's graphic. This method should be much faster than trying to resize and rotate the sprite every game loop.

GarageGothic

#6
monkey, In my experience, anything using RawRestoreScreen and creating DynamicSprites from background every game loop will pretty much always be slower than pure DynamicSprite deformation (even more so with the new Direct3D engine). Especially as this DynamicSprite would only be one or two pixels wide until rotated. Also, using a sprite would allow for better resolution (if it's a hi-res game) and let you draw the laser beam with gradients.

The only small problem about rotating the sprite, is that you must recalculate the x coordinate for the object every frame. But that's simple geometry and not too complicated.

magintz

#7
I've been fiddling around and I managed to sort this out, in case anyone has a similar problem. I will try monkeys script and see how that handles, or I can just put the objects into the background and animate the background manually if I want to change anything with the objects - which I think will work better anyhow as the laser will be gone by then.

Within the game script
Code: ags

/* ---------------
RawDrawLine laser
------------------ */
// Extend Laser
RawSetColor(47104); 
RawSaveScreen();
xpos = 212;
ypos = 22;
while (xpos > 59) {
  RawDrawLine(212,22,xpos,ypos);
  Wait(1);
  xpos = xpos - 2;
  ypos = ypos + 2;
}

// Set the timer (see repeatedly execute)
ypos = 173;
SetTimer(1, 25);

/*----------------------
End of RawDrawLine laser
------------------------*/


In repeatedly execute:
Code: ags

// Moves the laser beam in the background
if (IsTimerExpired(1)) {
if (ypos > 134) {
  RawRestoreScreen ();
  RawDrawLine(198,22,47,ypos);
  ypos--;
  SetTimer(1, 25);
}
}


Works a treat except for the overlay thing :P
When I was a little kid we had a sand box. It was a quicksand box. I was an only child... eventually.

SMF spam blocked by CleanTalk