ID:178876
 
I'm looking for an way to draw lasers in my game. What I'd like to do to represent this is just have a line drawn from the source to the target if they are close enough.

Can anyone tell me the proc if there is one to do this?

LJR
In response to Sob
Thanks but no thanks ;)
I'm the like to know how its done coder of BYOND! :P

LJR
In response to LordJR
LordJR wrote:
Thanks but no thanks ;)
I'm the like to know how its done coder of BYOND! :P

s_missile probably wouldn't suit your purposes there anyway, since it's designed for graphical missiles that fly to their targets. =P
In response to Spuzzum
Spuzzum wrote:
LordJR wrote:
Thanks but no thanks ;)
I'm the like to know how its done coder of BYOND! :P

s_missile probably wouldn't suit your purposes there anyway, since it's designed for graphical missiles that fly to their targets. =P

Yeah I knew, I just didn't want to insult him :)

LJR
In response to LordJR
Well in case anyone missed this, I can't find anything where it talked about Drawing.. What kinda procs are theses?? Is this new stuff since the Book came out?

LJR
In response to LordJR
I started working on the problem and this is what I have so far. It won't draw an entire line from the src to the target but it will create a laser pulse (one turf large) that is aligned with the target.
mob
verb
Shoot(var/mob/M as mob in oview(8))
var/hypotenuse = sqrt((M.x - x)**2 + (M.y - y)**2)
var/angle = round(arccos((M.x - x)/hypotenuse))
var/icon/I = new('laser2.dmi')
if(M.y > y)
angle *= -1
angle += 45
I.Turn(angle)
missile(I,src,M)


You need to draw the laser icon from the bottum left corner to the top right corner of the icon. It doesn't need to be continuous just with that orientation (meaning it could be several torpedoes instead of one continuous beam).

This will make use of the entire turf length of the turf. If you don't mind it partially filling the turf you can get rid of the angle += 45 line and make your icons from left center to right center (horizontally). It just depends on what you want.

Anyway, I might try to allow one continuous beam but I'll have to think about that because the shifts involved could be troublesome.
In response to LordJR
LordJR wrote:
Well in case anyone missed this, I can't find anything where it talked about Drawing.. What kinda procs are theses?? Is this new stuff since the Book came out?

There are no drawing procs (yet) in the /icon class, but icon.Blend() can be used to take special single-pixel icons and overlay them.
/*
This requires pixel.dmi to be a white pixel at the lower left corner
of an otherwise transparent pixmap.

x,y coords are 0-based, not 1-based; no limit checking is done, so
they should be 0-31.
*/


DrawPixel(icon/ic,x,y,color)
var/icon/pixel=new /icon('pixel.dmi')
pixel.Blend(color,ICON_MULTIPLY)
pixel.Shift(EAST,x)
pixel.Shift(NORTH,y)
ic.Blend(pixel,ICON_OVERLAY)

Obviously that proc is massively inefficient; it's better to cache a colored pixel first.

Lummox JR
In response to English
Ok.. I've not had much exp. with this so I'm wondering if anyone can suggest some ways that I could do this syntax wise.

I've drawn 3 framed animated icons of my lasers when they fire, since there are no draw commands yet. So what I need to know now, is how to check 3 spaces in front of the mob, also how to define which side of the mob is the front. So when they fire, it shots out the lasers up to 3 spaces ahead, if any objs or mobs are encounted during this check it stops, and does a check to see if its a valid target, if so damage is done.

LJR

ps. I have heard some people recommend the missle() for this, but I'm worried about this considering there is no movement from source to target like a missle, but a instant 3 tile line and anything in the way gets hit.
In response to LordJR
LordJR wrote:
Ok.. I've not had much exp. with this so I'm wondering if anyone can suggest some ways that I could do this syntax wise.

I've drawn 3 framed animated icons of my lasers when they fire, since there are no draw commands yet. So what I need to know now, is how to check 3 spaces in front of the mob, also how to define which side of the mob is the front. So when they fire, it shots out the lasers up to 3 spaces ahead, if any objs or mobs are encounted during this check it stops, and does a check to see if its a valid target, if so damage is done.

missile() is clearly not what you want. I believe you want a simple straight line between two arbitrary tiles. Well, then you're going to want an algorithm to make the icons for you:
/*
Draw a laser going dx tiles east, dy tiles north, centered
in each tile. This proc returns an associative list that's
meant to be cached for quick lookup. For convenience, keep
dx>=0.

'laser.dmi' should be a single icon, a white pixel at 16,16
and all other pixels transparent.

This laser is white. To color it in, I recommend using an associative
list as a cache to store the colored icons. The laser is a single
pixel line, but this code can be modified (not easily, mind you)
to produce thicker lines.
*/


proc/CreateLaser(dx,dy)
var/cachekey="[dx,dy]"
var/list/L=list()
var/icon/lasershifted=new /icon('laser.dmi')
var/unitstomove=max(dx,dy)*32
var/xinc1=0
var/yinc1=0
var/xinc2=0
var/yinc2=0
var/maindir=EAST
var/sidedir=(dy>=0)?NORTH:SOUTH
if(dx>dy)
xinc1=1
yinc2=(dy>=0)?1:-1
else
yinc1=(dy>=0)?1:-1
xinc2=1
maindir=sidedir
sidedir=EAST
var/swap=dx
dx=dy
dy=swap
var/mainsub=(dx>=0)?16:15
var/sidesub=(dy>=0)?16:15
dx=abs(dx)
dy=abs(dy)
var/centerx=0 // coords of current tile
var/centery=0
var/aside=dx
var/icon/current
for(var/n=0,n<=unitstomove,++n)
current=L["[centerx],[centery]"]
if(!current)
current=new /icon(lasershifted)
L["[centerx],[centery]"]=current
else
current.Blend(lasershifted,ICON_OVERLAY)
lasershifted.Shift(maindir,1,1) // wrap
aside+=dy
mainsub=(mainsub+1)&31
if(!mainsub)
centerx+=xinc1
centery+=yinc2
if(aside>dx+dx)
aside%=dx
lasershifted.Shift(sidedir,1,1) // wrap
sidesub=(sidesub+1)&31
if(!sidesub)
centerx+=xinc2
centery+=yinc2
lasercache[cachekey]=L
return L

I wrote that mostly as an exercise to see what I could come up with. Code to draw a thicker laser would be slightly harder because you'd need 1) to use ICON_ADD and icons with small circle and a black background, followed by a call to SwapColor() at the very end to replace black with the mask, and 2) to add to more than one icon at a time when the shifted circle covers more than one tile.

Lummox JR