• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Question My Ray Casting Game

B

Ben Hubble

Guest
Hello! I'm currently making a ray casting game (The illusion of 3D) and I've ran into a problem. I have made a script that draws whatever instance's sprite next to the game area (Where all the 2D stuff happens (i'll include a few pictures)). I've made a vision cone and whatever is in that vision cone is drawn to the screen, with adjusted size to make the illusion of 3D. I'll just show you my script:
Code:
///scr_draw_3d_obj(collision_line_length,how much to divide by,instance_id)

collLineLength = argument0;
divideby = argument1;
instance = argument2;

if(instance != undefined) {
sprite = draw_sprite(instance.sprite_index,instance.image_index,320,320);
sprite_xscale = collLineLength/divideby;
sprite_yscale = collLineLength/divideby;
sprite.image_xscale = sprite_xscale;
sprite.image_yscale = sprite_yscale;
}
The problem is that the sprite that I drew off to the left of my 2d game area, doesn't change size, but the even weirder part is that the left and top walls of the 2d game area change size! This is game breaking for me and any help would be appreciated!
If you would like, here is the code that draws my vision cone & gets the arguments for my script:

Code:
///Draw Vision Cone
draw_self();
draw_text(2,34,"FPS: " + string(fps));
direction = point_direction(x,y,mouse_x,mouse_y);

var length, lDir, rDir;
length = 250;

lDir = direction + 45;
rDir = direction - 45;

var ptnLeftX, pntLeftY, pntRightX, pntRightY;

pntLeftX = x + lengthdir_x(length, lDir);
pntLeftY = y + lengthdir_y(length, lDir);

pntRightX = x + lengthdir_x(length, rDir);
pntRightY = y + lengthdir_y(length, rDir);

draw_set_color(c_red);
draw_line(x, y, pntLeftX, pntLeftY);
draw_line(x, y, pntRightX, pntRightY);
draw_line(pntLeftX, pntLeftY, pntRightX, pntRightY);

draw_set_color(c_black);
for(i = lDir; i > rDir; i--)
{
  len = scr_get_length(length, lDir, rDir, i);
  rayCast = collision_line(x, y, x+lengthdir_x(len, i), y+lengthdir_y(len, i),obj_wall,false,true);
  draw_line(x,y,x+lengthdir_x(len, i), y+lengthdir_y(len, i));
  collisionLineLength = distance_to_point(x + lengthdir_x(len,i),y + lengthdir_y(len,i));
  scr_draw_3d_obj(collisionLineLength,100,rayCast);
}

draw_text(2, 2, direction);
scr_get_length is this: (I didn't make this script, I got it off of GMC)
Code:
/// scr_get_length(rayLength, leftDir, rightDir, angle);

// NOTE: This assumes that the angle between leftDir and rightDir is 90 degrees
// it's fairly easy to adjust it however.

var angl;
angl = argument1 - argument3;
if(angl == argument1 || angl == argument2) return argument0;
return argument0 * sin(degtorad(45)) / sin(degtorad(180 - 45 - (90 - angl)));
Check The Picture to understand better
 

Attachments

S

SyntaxError

Guest
draw_sprite doesn't return anything.

Remove the sprite = from "sprite = draw_sprite(instance.sprite_index,instance.image_index,320,320);"
and the "sprite." from the following two lines may fix this issue.

EDIT: It won't. If the object calling this script has a sprite that is also drawn, (which it looks like it may as you have a draw_self high up in the code block that calls this script) then you will need to save your current image_x/yscale's, then change the sprite index, the apply the scale changes, draw the sprite, change your sprite index back and then reapply the saved image_x/yscale's.

EDIT2: It appears that you are drawing a sprite from another instrance. You could instead of the above, change to image_x/yscale of that instance instead.

Code:
instance.image_xscale = collLineLength/divideby;
instance.image_yscale = collLineLength/divideby;
draw_sprite(instance.sprite_index,instance.image_index, 320, 320);
You may need to change the draw_sprite to draw_sprite_ext for the extra scale arguments but I'm not sure of that.
 
Last edited by a moderator:
B

Ben Hubble

Guest
draw_sprite doesn't return anything.

Remove the sprite = from "sprite = draw_sprite(instance.sprite_index,instance.image_index,320,320);"
and the "sprite." from the following two lines may fix this issue.

EDIT: It won't. If the object calling this script has a sprite that is also drawn, (which it looks like it may as you have a draw_self high up in the code block that calls this script) then you will need to save your current image_x/yscale's, then change the sprite index, the apply the scale changes, draw the sprite, change your sprite index back and then reapply the saved image_x/yscale's.

EDIT2: It appears that you are drawing a sprite from another instrance. You could instead of the above, change to image_x/yscale of that instance instead.

Code:
instance.image_xscale = collLineLength/divideby;
instance.image_yscale = collLineLength/divideby;
draw_sprite(instance.sprite_index,instance.image_index, 320, 320);
You may need to change the draw_sprite to draw_sprite_ext for the extra scale arguments but I'm not sure of that.
Thank you for the advice, now I see that I should be using draw_sprite_ext.
 
B

Ben Hubble

Guest
Screenshot (14).png Screenshot (15).png I seem to have another problem, that is probably really easy to do but I'm just being stupid. Basically, I've got my block in the middle of the room to change size as I move, and all the other blocks stay the same size, however, it gets smaller the closer I get and larger the further away I go. I would like it to get larger the closer I get, and smaller the further away I get. Currently the way I get the distance is this:
Code:
draw_set_color(c_black);
for(i = lDir; i > rDir; i--)
{
  len = scr_get_length(length, lDir, rDir, i);
  rayCast = collision_line(x, y, x+lengthdir_x(len, i), y+lengthdir_y(len, i),obj_wall,false,true);
  draw_line(x,y,x+lengthdir_x(len, i), y+lengthdir_y(len, i));

  if(rayCast != noone) {
  collisionLineLength = distance_to_point(rayCast.x,rayCast.y); //collision_line returns an instance id or no one if no instance was found btw
  scr_draw_3d_obj(collisionLineLength,100,rayCast);
  }
}
Then in scr_draw_3d_obj:
Code:
///scr_draw_3d_obj(coll_line_length,how much to divide by,instance_id)

collLineLength = argument0;
divideby = argument1;
instance = argument2;

draw_text(2,18,string(instance));

if(instance != noone) { //Just another safeguard so that I don't receive an error
spr = instance.sprite_index;
subimage = instance.image_index;
sprite_xscale = collLineLength/100/2;
sprite_yscale = collLineLength/100/2;
rot = instance.direction;
alpha = instance.image_alpha;
draw_sprite_ext(spr,subimage,320,320,sprite_xscale,sprite_yscale,rot,c_white,alpha);
}
What I would like to do is just invert the sprite_xscale and sprite_yscale to be larger as I get closer and smaller as I get further away, but I don't know how to do that. Please help!
 
S

SyntaxError

Guest
Although I suspect it doesn't, does image scale go from 0 to 1? If so, abs(image_scale -1) may work.

Otherwise, does it have a set maximum. If so, change it to a percentage and do the above.

There may be a more elegant way. I'm bad at math.
 
B

Ben Hubble

Guest
Although I suspect it doesn't, does image scale go from 0 to 1? If so, abs(image_scale -1) may work.

Otherwise, does it have a set maximum. If so, change it to a percentage and do the above.

There may be a more elegant way. I'm bad at math.
Oh it doesn't work completely, I would like it so that if you're directly against a wall, the wall should cover up the whole screen, then progressively get smaller as you walk away, so image_xscale & image_yscale should go from 0 to over 1. any idea how to make this?
 
Last edited by a moderator:
S

SyntaxError

Guest
I can't think of a way.

GMC maths guru's, your up.
 
C

Ctl-F

Guest
As far as I know, image_scale doesn't have a maximum. If image_scale is 1 the object is 100% size, if its two, the image is twice as big, if a scale is negative the image size will follow abs(image scale) but the image will be flipped.

What you can do is use a fraction. You need to decide at what distance you want the object to be drawn at 100% size however

Code:
scale = n / distance;
n being the distance away the camera must be for the object to be drawn at 100%

This way the greater the distance is the smaller the object will be. But if the distance is smaller than n the object will get larger.

You can figure out how many times larger the object must be by dividing the width(or height) of the object by the width(or height) of the display.

Then you can use cross multiplication on the ratios to figure out the correct distance
Code:
scale = objwidth / displaywidth
scale / 1 == 1 / n
/////So n = scale
Edit: sorry, simple math mistake,
n = 1/scale
You can and should tinker with this equation to get it to look like what you want it to look like, this is just a starting point.

Does that answer your question?
 
Last edited by a moderator:
B

Ben Hubble

Guest
As far as I know, image_scale doesn't have a maximum. If image_scale is 1 the object is 100% size, if its two, the image is twice as big, if a scale is negative the image size will follow abs(image scale) but the image will be flipped.

What you can do is use a fraction. You need to decide at what distance you want the object to be drawn at 100% size however

Code:
scale = n / distance;
n being the distance away the camera must be for the object to be drawn at 100%

This way the greater the distance is the smaller the object will be. But if the distance is smaller than n the object will get larger.

You can figure out how many times larger the object must be by dividing the width(or height) of the object by the width(or height) of the display.

Then you can use cross multiplication on the ratios to figure out the correct distance
Code:
scale = objwidth / displaywidth
scale / 1 == 1 / n
/////So n = scale
Edit: sorry, simple math mistake,
n = 1/scale
You can and should tinker with this equation to get it to look like what you want it to look like, this is just a starting point.

Does that answer your question?
Well, the first part does do it, but the second part, I just worked out on a calculator, would be this equation (without the variables) in my case:
32 / 1366 / 1 / (1 / 0.02342606149) = 0.00054878035. Yeah, I don't think that is gonna work. I even got gamemaker to write out what scale is, it says 0.00 every time. Also, sorry for the late reply, video games that aren't made by me and don't suck are addicting :3
 
C

Ctl-F

Guest
Wow, I just re-read that and I realized it was about as clear as mud.
Sorry about that, I was doing it in my head at the time, and sometimes it's hard to keep everything straight. XD
Here is what I meant:
Code:
var nScale = [displayWidth] / [imageWidth]; // not imageWidth / displayWidth
var scale = nScale / (distance + 0.001); // we add the 0.001 so we are never dividing by 0
that is the basis for what you are looking for, however in my opinion the growing/shrinking happen much too quickly, so I recommend changing it to be this:

Code:
var nScale = [displayWidth] / [imageWidth];
var scale = nScale / ((point_distance(x+lengthdir_x([imageWidth]/2, [direction to camera]), y+lengthdir_y([imageHeight]/2, [direction to camera]), camera.x, camera.y)+0.001)*0.1);
By dividing the distance by 10 (or multiplying it by 1/10th) the object stays bigger longer.
That's just my recommendation, however, do what looks right to you.
 
Top