The Problem
I'm creating a sword that 'swings' 90 degrees.
This is done using a Unity animation:
When a player attacks, such a sword is created. Depending on the player's direction, the sword will be mirrored across the X or Y axis.
But when the player attacks to the left, he attacks from the bottom and up, instead of opposite.
Code
Here's the code I use to determine which way we should mirror the sword:
void changeDirection()
{
print(Direction);
if(Direction == Entity.direction.RIGHT)
gameObject.transform.localScale = new Vector3(-1, 1, 1);
if (Direction == Entity.direction.LEFT)
{
gameObject.transform.localScale = new Vector3(1, -1, 1);
}
if (Direction == Entity.direction.DOWN)
gameObject.transform.localScale = new Vector3(-1, -1, 1);
}
Up isn't here, because that's default.
Why can't you just rotate it?
Because, the animation already rotates the sword, so it 'overwrites' whatever I do. That's my theory, at least.
Video Example of Problem
http://a.pomf.se/vgxumj.webm
Add a child object to the Weapon_Swing transform, and spawn the sword in the child object. This should ensure that you can set the localRotation of the sword independent of the animation.
I would create one animation file, pretty sure thats what you have already. Then parent it to other GameObject. Change direction of the parent game object in code.
if(Direction == Entity.direction.RIGHT)
gameObject.transform.localRotation = Quaternion.Euler(new Vector3(90, 0, 1));
if (Direction == Entity.direction.LEFT)
{
gameObject.transform.localRotation = Quaternion.Euler(new Vector3(0, 90, 1));
}
if (Direction == Entity.direction.DOWN)
gameObject.transform.localRotation = Quaternion.Euler(new Vector3(90, 0, 1));
For those in the future looking for an easy solution, LateUpdate appears to get called after the animation is applied, so any rotations done in LateUpdate don't get overwritten.
Related
I tried to make a jump look realistic, while I watched through the Videos:
The Natur of Code - The Coding Train
I got into PVectors. I strongly recomend watching him. But to get to my question, everything seems to work, exept that it draws the rectangle (my PVector) the way I want.
void keyPressed() {
if (keyCode == UP) {
for (int i = 0; i < 16; i++) {
location.sub(velocity);
velocity.sub(acceleration);
h.display();
background(0);
}
velocity.set(0, 15);
}
}
That's the Code, I expect it to "jump", but nothing realy happens. You can see that the rectangle get's drawn again (on the same spot), but there's no movement. It's definitly an issue with the drawing of the background or something, I don't know what exaclty though.
The nature of your question is unclear. You mentioned issues regarding the background interfering with your rectangle after the UP arrow key is pressed. This is likely because background(0) is called immediately after h.display(). I would remove background(0) from your loop if it's a display issue.
Other than that, there seem to be other issues with the loop itself. When the UP key is pressed, h is affected by acceleration only for 16 frames. To make your object more realistic, gravity (or whatever acceleration you choose) should constantly be acting upon the object.
With that in mind, here's a solution for you.
void keyPressed() {
if (keyCode == UP) {
// Make the character 'jump' upwards when the UP arrow is pressed.
// Setting the velocity should be the only thing happening when the key is pressed.
velocity.set(0, -2);
}
}
void draw() {
// Reset the background each frame so rectangles don't overlap.
background(255);
// Always draw the rectangle AFTER resetting the canvas.
h.display();
// Change the object's location by it's velocity.
location.add(velocity);
// And chance the object's velocity by it's acceleration.
// Since acceleration is the acting force of gravity in this situation, acceleration need not be changed.
velocity.add(acceleration);
// Prevent the rectangle from falling through the bottom of the canvas.
if(location.y > height - 5) location.y = height - 5;
}
// You negleteced to define your variables in your code snippet. Here they are.
PVector location = new PVector(0, 0);
PVector velocity = new PVector(0, 0);
PVector acceleration = new PVector(0, 0.1); // Notice that acceleration's y-value is 0.01. This is so you can see the effect of gravity.
// Define your rectangle object.
Object h = new Object();
class Object {
Object() {} // Constructor.
void display() {
// Draw the rectangle at the x- and y-positions of the location vector.
// The '+ width/2' places it at the center of the screen.
rectMode(CENTER);
rect(location.x + width/2, location.y, 10, 10);
}
}
I am new to three.js and modifying some existing code.
The existing code is rendering a graph using "THREE.BufferGeometry" + "THREE.Points"
var geometryPc = new THREE.BufferGeometry();
var materialPc = new THREE.ShaderMaterial({....});
this.mesh = new THREE.Points(geometryPc, materialPc);
I am trying to put a label text on every node which moves with the node.
I tried:
I tried creating "THREE.Sprite" for each node and then assigning it positions relative to that node.
let texture = new THREE.Texture(canvas);
let spriteMaterial = new THREE.SpriteMaterial({map: texture, useScreenCoordinates: false});
let sprite = new THREE.Sprite(spriteMaterial);
Thats seems to be working but UI becomes too heavy when number of nodes are relatively high.
I would prefer to use "BufferGeometry" to create texts as well. But could not find a way to do that.
Is there any better way to put text on the nodes?
Your approach with sprites, altough by far the most obvious, unfortunately will not be sufficient. Each sprite, if I understand correctly, creates its own mesh with its own texture, so each causes a separate draw call. This approach is not scalable.
The way I did it was to make a shader capable of rendering different parts of an image and then make an image containing letters (in a monospace font). Then, to each point in geometry (a place where a label should be rendered), I pass such a set of parameters (shader attributes) for every letter rendered:
positionX: this.position.x, //position of entire label
positionY: this.position.y,
positionZ: this.position.z,
colorR: this.color.r,
colorG: this.color.g,
colorB: this.color.b,
colorA: this.visible ? (this.finalAlpha) : 0,
scale: this.camera.zoom, //scale must depend on camera zoom
spriteNumber: this.getTextPosition(lines[i][j]), //see below ;p
offset: j + i * 32768, //this is for positioning one particular letter,
//x and y merged together because I ran out of parameters
size: this.size
i and j are a "x" and "y" position of a letter in a label, the shader does offsetting by itself; other parameters should be more or less obvious :)
ParticleLabel.prototype.getTextPosition = function(symbol){
switch(symbol){
case '0': return 1;
case '1': return 2;
case '2': return 3;
(...)
case 'A': return 20;
case 'B': return 21;
case 'C': return 22;
(...)
I can't show entire code as I made it for a commercial solution, but I'll make an example on codepen or sth later on to show a working solution.
I'm trying to activate different visuals by pressing different keys. For example, when I press "z" or "Z", an ellipse on a specific position flows down, leaving a trace behind. If I wait for it to reach the canvas border, there's no problem but when I press "0" which activates another ellipse on another position to do the same thing, the ellipse of "z"/"Z" stops flowing. It also happens when I press the same key before the ellipse reaches canvas border. How can I fix this? When I started to code this, I didn't know classes and objects, then I learned and tried to solve it by using creating an object but it got worse, ellipses didn't work at all. I want the first ellipse to continue until the border even if I press another key while it's on its way.
Another thing is I wanted them to fade out after a short time, so I drew semi-transparent rectangles on canvas which seems very primitive to me. Would you suggest a different way? This is less important but it would be better to have them completely fade over time rather than leaving a slight trace.
Here's my code, I cleaned irrelevant parts to make it look more understandable:
void setup() {
size(640, 500);
background(bgRenk);
frameRate(60);
colorMode(HSB);
noStroke();
}
int bgRenk = #e7e7e7;
int C3Yer;
int C3Y;
int Fd6Yer;
int Fd6Y;
void draw() {
// This part probably sucks because it's a primitive solution to make ellipses fade out by putting semi-transparent rectangles on the canvas.
fill(bgRenk, 10);
rect(0, 0, 640, 500);
// I basically map x and y positions to hue and opacity.
float C3Renk= map(C3Yer, 0, width, 0, 255);
float C3Opak = map(C3Y, height, 0, 0, 200);
// When z/Z is pressed, an ellipse appears and goes down, leaving trace behind.
if (key == 'z' || key == 'Z') {
C3Yer = 10;
fill(C3Renk, 255, 255, C3Opak);
ellipse(C3Yer, C3Y, 20, 20);
C3Y += 20;
}
if (key == '0') {
// Same mapping and ellipse thing.
float Fd6Renk= map(Fd6Yer, 0, width, 0, 255);
float Fd6Opak = map(Fd6Y, height, 0, 0, 200);
Fd6Yer = 630;
fill(Fd6Renk, 255, 255, Fd6Opak);
ellipse(Fd6Yer, Fd6Y, 20, 20);
Fd6Y += 20;
}
}
void keyPressed() {
if (key == 'z' || key == 'Z') {
// When z/Z is pressed, y position of those ellipses are reset.
C3Y = 10;
}
if (key == '0') {
// Same reset thing.
Fd6Y = 10;
}
}
Thank you for your time.
Problem with creating new ellipse while other is still flowing is with variable key which always contains the value of the most recent key used (for more see). So when you press any key after "z" your ellipse will stop being drawn.
You can avoid this using global variables indicating which ellipses should be drawn.
But I would suggest using creating objects that will have defined state (position, color, opacity) and will be stored inside array or list. It will also help you with fading so find a time and read more about classes and objects. On processing site you can find nice tutorials like this one
But because you sad you already tried creating objects and i don't works I will give you few tips and basic example of such a class:
class Ball {
float x, y; // position of ball
color col = 10; // color of ball
int opac = 255; // opacity of ball
Ball(float _x, float _y) {
x = _x;
y = _y;
}
void move() {
y += 20;
opac -= 10;
}
void display() {
fill(col, 255, 255, opac);
ellipse(x, y, 20, 20);
}
}
Then you can create new ball objects:
void mousePressed() {
//this will create new ball on mouse position
balls.add( new Ball(mouseX, mouseY) );
}
and store them into ArrayList like this:
ArrayList<Ball> balls = new ArrayList();
Last thing that you need to do is display and move all balls within draw method.
for (Ball b : balls) // for each ball in list
{
b.display(); // first display ball
b.move(); // move and change opacity
}
This is very basic example and should be improved but I hope it will help you with understanding of classes.
Hi How do I make bullets to collide with the objects in Processing ?
Bullets are fired and being translated and rotated
but whenever i try to use function dist() it always gives me 0 as the position of the vector
How do i get the correct vector position if i want the bullet to collide with objects using distance and make the the other object disappear ?
Here's the code
void move(){
passed = passed + time;
if (passed > bulletLife) {
alive = false;
}
forward.x = sin(theta);
forward.y = -cos(theta);
float speed = 15.0f;
velocity = PVector.mult(forward, speed);
side.add(forward);
void display(){
pushMatrix();
translate(side.x, side.y);
rotate(theta);
stroke(255);
ellipse(side.x, side.y, 30, 30);
popMatrix();
Thanks
You're getting 0 from dist() because translate() moves the coordinate system! I think, more than your question, you need to reconsider your code overall. You translate to side.x, side.y (which will then be 0,0 until you call popMatrix()) but then you draw the ellipse at side.x, side.y which is offset from its actual position.
In other words: if the position is 100,200, you're actually drawing the object at 200,400!
If you skip the translate() part, you can use this to draw your object:
void display() {
stroke(255);
ellipse(side.x, side.y, 30,30);
}
And this to check collision:
if (dist(side.x, side.y, bullet.x, bullet.y) == 0) {
collision = true;
}
else {
collision = false;
}
You can also see my collision-detection functions for Processing, which have lots of examples that might help.
I have made the game, "Breakout". A small fun side-project.
Now, I usually do not make games, so collision-handling is not something I normally think about.
I have a paddle, a ball and some bricks.
For now, when there is a collision (I draw rectangles around each of the objects mentioned), I simply change the Y value of the ball to -Y.
This works fine, EXCEPT if the ball hits a brick from the side (either East or West). The side-effect is not pretty and ruins the gameplay.
I think I can safely assume that instead of the above technique, I need to change the X value to -X when this happens.
So far I have: if (ballRect.IntersectsWith(brickRect))
ballRect and brickRect being rectangles around each object.
Now, what if I created a rectangle around the eastern border of the brick, the western border, etc? I guess the width would be about a pixel.
If collision happens with western or eastern rectangle, then the balls X value should be -X.
And vice versa.
What about the corners though? Should I just randomly choose which rectangle to control of x corner?
Or perhaps should I make a rectangle around each corner? the rectangle being 1*1 in side.
If there is a collision => -x AND -y values of the ball?
Please share your thoughts.
Here is the process so far:
foreach (var brick in Bricks)
{
if (brick.IsAlive)
{
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if (ballRect.IntersectsWith(brickRect)) //Ball has hit brick. lets find out which side of the brick
{
var brickRectNorth = new Rectangle(brick.X, brick.Y + BrickHeight, BrickWidth, 1);
var brickRectSouth = new Rectangle(brick.X, brick.Y, BrickWidth, 1);
var brickRectEast = new Rectangle(brick.X, brick.Y, 1, BrickHeight);
var brickRectWest = new Rectangle(brick.X + BrickWidth, brick.Y, 1, BrickHeight);
if (ballRect.IntersectsWith(brickRectNorth) || ballRect.IntersectsWith(brickRectSouth))
{
//STUFF that makes ball.y = -ball.y
}
if (ballRect.IntersectsWith(brickRectWest) || ballRect.IntersectsWith(brickRectEast))
{
//STUFF that makes ball.x = -ball.x
}
}
}
}
Rather than looking for rectangle intersections, I'd intersect the actual edges. At the corner, your ball is touching two edges simultaneously, so its motion vector should be affected by both.
I would keep the single rectangle for collision detection, since that reduces the number of rectangles you need to test in your outer loop, but then once a collision with a brick has been detected, go into an inner loop to detect which edge it was that was hit. If you just test each edge and adjust the vector accordingly for each one, the corner will come for free (as long as you don't break out of the loop when you find the first intersecting edge).
Edit: In response to your updated question:
Actually, this is how I would do it (given your code, this appears to be C# 3.0, so that's what I've assumed below):
foreach(var brick in Bricks) {
if(brick.IsAlive) {
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if(ballRect.IntersectsWith(brickRect)) {
// Ball has hit brick. Now let's adjust the ball's vector accordingly
// Convenience variables. Compiler will probably inline.
var brickLeft = brick.X;
var brickRight = brick.X + BrickWidth;
var brickTop = brick.Y;
var brickBottom = brick.Y + BrickHeight;
var ballLeft = ball.X - ball.Radius;
var ballRight = ball.X + ball.Radius;
var ballTop = ball.Y - ball.Radius;
var ballBottom = ball.Y + ball.Radius;
// Test which vector(s) we need to flip
bool flipX = (ballRight >= brickLeft || ballLeft <= brickRight);
bool flipY = (ballTop >= brickBottom || ballBottom <= brickTop);
// Flip the vectors (there are probably ways to optimize this,
// too, but without seeing your code I can't tell).
if(flipY) {
// Stuff that makes ball.y = -ball.y
}
if(flipX) {
// Stuff that makes ball.x = -ball.x
}
}
}
}
Basically, the point is that since you already know the ball actually intersects the brick, you can simplify to a simple box test, which is much faster. Also, there's no need to create extra rectangles for the edges -- just use the edges of the rectangle you already have.