SpriteKit How to add laser beam and resize it at collision point - sprite

I'm developing my first game with SpriteKit and I need to shoot a laser beam. I don't know how to do this since I don't know the size of the laser sprite, does it have to be with size of the screen height and crop the image when a collision is detected? can anyone point me to the right directions please? Have no idea about this XD
Thanks for your comments :D

This could be done by line-of-sight detection system described here in the section Searching for physics bodies :
Useful method would be enumerateBodiesAlongRayStart:end:usingBlock: from SKPhysicsWorld class which enumerates all the physics bodies in the scene that intersect a ray.
Basically you have to set start point and search for end point using the method above.When you know where is the intersection point(end point of laser beam) you can easily draw it.

This is a way late response, but I've got a really nice solution. Here's what it looks like (Swift 3):
In my code I'm calling this when I rotate the node I want the laser to shoot out of:
self.laser = SKShapeNode()
laser.lineWidth = 6
laser.glowWidth = 8
laser.strokeColor = .red
let _ = isTargetVisibleAtAngle(startPoint: startPoint, angle: selectedBeam!.zRotation + (CGFloat.pi / 2), distance: frame.size.height)
And this is the method. Obviously you put in whatever angle you want. The "foundOne" thing is so that it stops on the first object if that ray crosses through multiple targets
func isTargetVisibleAtAngle(startPoint: CGPoint, angle: CGFloat, distance: CGFloat) -> Bool {
let rayStart = startPoint
let rayEnd = CGPoint(x: rayStart.x + distance * cos(angle),
y: rayStart.y + distance * sin(angle))
let path = CGMutablePath()
path.move(to: rayStart)
path.addLine(to: rayEnd)
laser.path = path
var foundOne = false
let _ = physicsWorld.enumerateBodies(alongRayStart: rayStart, end: rayEnd) { (body, point, vector, stop) in
if !foundOne {
foundOne = true
let p = CGMutablePath()
p.move(to: rayStart)
p.addLine(to: point)
self.laser.path = p
}
}
return false
}

Related

godot make Physics2dServer visible in game

this is my example code i also have Debug (visible collision shapes on) and I still can't see anything in game, my goal is to add a circle collision shape and be able to see in game
func create_area(mouse_position):
var position = mouse_position
var _shared_Area = Area2D.new()
var _circle_shape = Physics2DServer.circle_shape_create()
#_circle_shape.visible = true
Physics2DServer.shape_set_data(_circle_shape, 128)
print(" physics server ",Physics2DServer.ray_shape_create())
Physics2DServer.area_add_shape(_shared_Area.get_rid(), _circle_shape, xform )
Physics2DServer.area_set_collision_layer(_shared_Area, 1)
Physics2DServer.area_set_collision_mask(_shared_Area, 1)
Physics2DServer.area_set_monitorable(_shared_Area, true)
Physics2DServer.area_set_space(_shared_Area, get_world_2d().space)
Physics2DServer.area_set_transform(_shared_Area, Transform2D(1.0 , position))
Physics2DServer.area_set_area_monitor_callback(_shared_Area, self, 'debug_overlap')
func debug_overlap(_1,_2,_3,_4,_5):
print('overlap!!')

Attach sprite to Bullet - Box2D LibGDX kotlin

I'm following some tutorials to be able to implement the parabolic motion. In debug everything works correctly, the parabolic motion responds correctly and the result works. Now I would like to insert a Sprite, and here my problems begin. In fact, the sprite perfectly performs the rotations of the object that is carrying out the parabolic motion but it absolutely does not follow the X and Y coordinates. thank you in advance:
Bullet function:
private fun createBullet() {
val circleShape = CircleShape()
circleShape.radius = 0.5f
circleShape.position = Vector2(convertUnitsToMeters(firingPosition.x), convertUnitsToMeters(firingPosition.y))
val bd = BodyDef()
bd.type = BodyDef.BodyType.DynamicBody
bullet = world!!.createBody(bd)
bullet!!.createFixture(circleShape, 1f)
circleShape.dispose()
val velX = abs(MAX_STRENGTH * -MathUtils.cos(angle) * (distance / 100f))
val velY = abs(MAX_STRENGTH * -MathUtils.sin(angle) * (distance / 100f))
bullet!!.setLinearVelocity(velX, velY)
}
How I'm trying to create sprite:
override fun render(delta: Float) {
sprite.setPosition(bullet!!.position.x - sprite.width / 2,
bullet!!.position.y - sprite.height / 2)
sprite.rotation = Math.toDegrees(bullet!!.angle.toDouble()).toFloat()
batch!!.use {
it.draw(sprite, sprite.x, sprite.y, sprite.originX,
sprite.originY,
sprite.width, sprite.height, sprite.scaleX, sprite.scaleY, sprite.rotation)
}
}
This is an incorrect way to use the Sprite class. There is an unfortunate design decision in libGDX that Sprite is a subclass of TextureRegion, which allows you you pass it to SpriteBatch.draw() as if it is a TextureRegion. When you do this, it ignores all of the settings on the Sprite.
If you use the Sprite class, you must use Sprite.draw() instead of SpriteBatch.draw().
In my opinion, you should not use the Sprite class at all. You should write your own game object class that has the exact parameters you need and maybe keeps a reference to a TextureRegion. Then when you draw it using SpriteBatch.draw, you pass all the relevant data for position, rotation, etc. Then you are not having to keep redundant copies of your box2d body data in sync.

Phaser 3 - Fix a shape into the camera view

I am trying to draw a minimap from a randomly generated matrix that represents my level.
To do so, I am drawing black or white little squares one by one to represent the matrix visually (I don't know if it the best way to do that with phaser, actually, I am a beginner with this framework).
The map draws correctly but its position is bound to the world not to camera, so when I move it is not visible anymore.
Here is the code I use to draw the map:
generate() {
let wallsGraphics = this._scene.add.graphics({fillStyle : {color : LabyrinthConfig.MAPS.MINI_MAP.WALLS_COLOR}});
let pathGraphics = this._scene.add.graphics({fillStyle : {color : LabyrinthConfig.MAPS.MINI_MAP.PATH_COLOR}});
// Draw the map
let y = 0;
for (let line of this._matrix) {
let x = 0;
for (let cell of line) {
let rect = new Phaser.Geom.Rectangle();
rect.width = LabyrinthConfig.MAPS.MINI_MAP.CELL_WIDTH;
rect.height = LabyrinthConfig.MAPS.MINI_MAP.CELL_HEIGHT;
rect.x = LabyrinthConfig.MAPS.MINI_MAP.POSITION_X + x * LabyrinthConfig.MAPS.MINI_MAP.CELL_WIDTH;
rect.y = LabyrinthConfig.MAPS.MINI_MAP.POSITION_Y + y * LabyrinthConfig.MAPS.MINI_MAP.CELL_HEIGHT;
cell === 0 ? wallsGraphics.fillRectShape(rect) : pathGraphics.fillRectShape(rect);
x++;
}
y++;
}
}
Any help on how to fix this map to the camera view ?
Set scroll factor of your graphics objects to 0.
wallsGraphics.setScrollFactor(0);
pathGraphics.setScrollFactor(0);

Rotating object relative to mouse position

At the moment I'm using the dot product of the mouse position and (0, 1) to generate radians to rotate an object, in three.js
Code below, works ok but the object 'jumps' because the radian angle skips from positive to negative when the clientX value goes between window.innerWidth / 2
onDocumentMouseMove : function(event) {
// rotate circle relative to current mouse pos
var oldPos = new THREE.Vector2(0, 1);
Template.Main.mouseCurrPos = new THREE.Vector2((event.clientX / window.innerWidth ) * 2 - 1, - (event.clientY / window.innerHeight) * 2 + 1);
Template.Main.mouseCurrPos.normalize();
//Template.Main.projector.unprojectVector(Template.Main.mouseCurrPos, Template.Main.scene);
var angle = oldPos.dot(Template.Main.mouseCurrPos);
Template.Main.mousePrevPos.x = event.clientX;
Template.Main.mousePrevPos.y = event.clientY;
if (event.clientX < window.innerWidth / 2) {
Template.Main.circle.rotation.z = -angle;
}
else {
Template.Main.circle.rotation.z = angle;
}
console.log(Template.Main.circle.rotation.z);
}
However if I add this to assign the value to oldPos:
if (event.clientX < window.innerWidth / 2) {
oldPos = new THREE.Vector2(0, -1);
}
else {
oldPos = new THREE.Vector2(0, 1);
}
Then the "jumping" goes but the effect of rotation is inverted when the mouse is on the left of the window.
I.e. mouse going up rotates anti-clockwise and vice-versa which is not desired.
It's frustrating.
Also if I keep the oldPos conditional assignment and leave out the conditional negation of the angle instead, the jumping comes back.
You can see a demo here: http://theworldmoves.me/rotation-demo/
Many thanks for any tips.
Why are you using the result of the dot product as the angle (radians)? The dot product gives you the cosine of the angle (times the magnitude of the vectors, but these are a unit vector and a normalized vector, so that doesn't matter).
You could change your angle computation to
var angle = Math.acos(oldPos.dot(Template.Main.mouseCurrPos));
However, you may get the wrong quadrant, since there can be two values of theta that satisfy cos(theta) = n. The usual way to get the angle of a vector (origin to mouse position) in the right quadrant is to use atan2():
var angle = Math.atan2(Template.Main.mouseCurrPos.y,
Template.Main.mouseCurrPos.x);
This should give the angle of the mouse position vector, going counterclockwise from (1, 0). A little experimentation can determine for sure where the zero angle is, and which direction is positive rotation.

what parameters of CIVignette mean

I check CIVignette of Core Image Filter Reference at
http://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/filter/ci/CIColorControls
and play around a with the parameters:
inputRadius
inputIntensity
and still have not exactly understood what each parameter effects. Could please someone explain?
Take a look at wiki understand what vignetting in photography means.
It is the fall of of light starting from the center of an image towards the corner.
Apple does not explain much about the the params.
obviously the radius specifies somehow where the vignetitting starts
the param intensity i expect to be how fast the light goes down after vignetting starts.
The radius may not be given in points, a value of 1.0 relates to your picture size.
Intensity is definitely something like 1 to 10 or larger number. 1 has some effects, 10 is rather dark already.
The radius seems to be in pixel (or points). I use a portion of image size (says 1/10th of width) and the effect is pretty good! However, if the intensity is strong (says 10), the radius can be small (like 1) and you can still see the different.
Turns out there is an attributes property on CIFilter that explains its properties and ranges.
let filter = CIFilter(name: "CIVignette")!
print("\(filter.attributes)")
Generates the following output:
[
"CIAttributeFilterDisplayName": Vignette,
"CIAttributeFilterCategories": <__NSArrayI 0x6000037020c0>(
CICategoryColorEffect,
CICategoryVideo,
CICategoryInterlaced,
CICategoryStillImage,
CICategoryBuiltIn
),
"inputRadius": {
CIAttributeClass = NSNumber;
CIAttributeDefault = 1;
CIAttributeDescription = "The distance from the center of the effect.";
CIAttributeDisplayName = Radius;
CIAttributeMax = 2;
CIAttributeMin = 0;
CIAttributeSliderMax = 2;
CIAttributeSliderMin = 0;
CIAttributeType = CIAttributeTypeScalar;
},
"CIAttributeFilterName": CIVignette,
"inputImage": {
CIAttributeClass = CIImage;
CIAttributeDescription = "The image to use as an input image. For filters that also use a background image, this is the foreground image.";
CIAttributeDisplayName = Image;
CIAttributeType = CIAttributeTypeImage;
},
"inputIntensity": {
CIAttributeClass = NSNumber;
CIAttributeDefault = 0;
CIAttributeDescription = "The intensity of the effect.";
CIAttributeDisplayName = Intensity;
CIAttributeIdentity = 0;
CIAttributeMax = 1;
CIAttributeMin = "-1";
CIAttributeSliderMax = 1;
CIAttributeSliderMin = "-1";
CIAttributeType = CIAttributeTypeScalar;
},
"CIAttributeFilterAvailable_Mac": 10.9,
"CIAttributeFilterAvailable_iOS": 5,
"CIAttributeReferenceDocumentation": http://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIVignette
]
inputRadius is a float between 0 and 2 that affects the 'size' of the shadow.
inputIntensity is a float between -1 and 1 that affects the 'darkness' of the filter.

Resources