http://davzy.com/gameA/
I can't figure out a smart way to get gravity. Now with this it detects which block the character is over but it does't drop to that block!
Is there a better way to do gravity? I'd like to do this without a game library.
I don't know what you mean by "get gravity"; your question is unclear. I assume that if you can detect when the block is over, you can use the following formula:
s(t) = ut + 1/2at2
Where s is the distance at time t, u is the initial velocity (which in your case would be zero), and a is the acceleration (on Earth this is 9.8m/s2). Essentially you would be adjusting the top position of your object based on the value you get at time t (so original top position of object + s(t)). I would imagine you would use some sort of animation loop. Perhaps a setInterval. Maybe others with more experience in Javascript animation can chime in about the best way to implement this. However, this would be the formula that you would be using to figure out where the object is at time t, if it falls.
Basically gravity in a platformer goes like this:
var currentGrav = 0.0;
var gravAdd = 0.5; // add this every iteration of the game loop to currentGrav
var maxGrav = 4.0; // this caps currentGrav
var charPosY = getCharPosY(); // vertical position of the character, in this case the lower end
var colPosY = getColDow(); // some way to get the vertical position of the next "collision"
for(var i = 0; i < Math.abs(Math.ceil(currentGrav)); i++) { // make sure we have "full pixel" values
if (charPosY == colPosY) {
onGround = true;
break; // we hit the ground
}
onGround = false;
charPosY++;
}
Now to jump one could simply do this:
if (jumpKeyPressed && onGround) {
currentGrav = -5.0; //
}
You can, if you want(and understand C), check out my game for a basic platformer(with moving platforms) here:
http://github.com/BonsaiDen/Norum/blob/master/sources/character.c
Related
I'm newbie trying to build a game. I have an ant when you click on it it disappears and appears again somewhere else.
I want to make more than one ant appear at the same time and they get destroyed when you click on them. Also I want all of them move randomly from the top of the screen to the bottom of the screen. How to do so?
var ant : GameObject;
var scoreText : GameObject;
var livesText : GameObject;
var walkingSpeed : double;
var livesNumber : int;
var scoreNumber : int;
function Start () {
ant = GameObject.Find("Ant");
scoreText = GameObject.Find("Score");
livesText = GameObject.Find("Lives");
//Initialize the values of walking speed
walkingSpeed = 0.0;
livesNumber = 3;
scoreNumber = 0;
//Initialize the GUI components
livesText.GetComponent(UI.Text).text = "Lives Remaining: " + livesNumber;
scoreText.GetComponent(UI.Text).text = "Score: " + scoreNumber;
//Place the ant in a random position on start of the game
ant.transform.position.x = generateX();
ant.transform.position.y = generateY();
}
function Update () {
if(ant.transform.position.y < -4.35 && livesNumber > 0){
livesNumber -= 1;
livesText.GetComponent(UI.Text).text = "Lives Remaining: " + livesNumber;
generateCoordinates();
}else if(ant.transform.position.y < -4.35 && livesNumber == 0){
Destroy(GameObject.Find("Ant"));
gameOver();
}else{
ant.transform.position.y -= walkingSpeed;
}
}
function gameOver(){
Application.LoadLevel("GameOver");
}
//Generates random x
function generateX(){
var x = Random.Range(-2.54,2.54);
return x;
}
//Generates random y
function generateY(){
var y = Random.Range(-4.0,3.8);
return y;
}
//Move the "Ant" to the new coordiantess
function generateCoordinates(){
//You clicked it!
scoreNumber += 1;
//Update the score display
scoreText.GetComponent(UI.Text).text = "Score: " + scoreNumber;
ant.transform.position.x = generateX();
ant.transform.position.y = generateY();
}
//If tapped or clicked
function OnMouseDown(){
//Place the ant at another point
generateCoordinates();
//Increase the walking speed by 0.01
walkingSpeed += 0.01;
}
First of all, UnityScript is now deprecated for a while, so I think a good practice should be to update your Unity version and code in C# as now it's the main language used.
Try to avoid Game.Find() which is not a good way to reference GameObject. Instead you could create a prefab of your 'ant' and instantiate it as many time you want in random positions like that :
public GameObject antPrefab;
void GenerateAnt()
{
//create a new position from random X and Y
Vector2 position = new Vector2(generateX(), generateY());
//Instantiate a new ant gameobject from the prefab and set position and rotation
GameObject newAnt = Instantiate(antPrefab, position, Quaternion.identity)
}
Now if you have multiple ants, you need to loop for each ant to update the position of each ant.
Don't forget to link your prefab in your public field in the editor ! ;)
Your code is made around having only one specific ant. You need to make the code agnostic to specific ants.
But before going into specifics;
Please consider moving to C#, it'll make your life a lot easier.
I will assume this is 2D. If 3d, simply change the Vector2s to Vector3 and remove 2d from trigger method.
I'll write the example code in C#
So basically, what you have today is:
Spawn an ant.
If user clicks the ant, move it to start.
If ant goes too far, you lose a life & remove it.
What you want it
Spawn any number of ants in random position.
If user clicks an ant, remove it(?).
If ant reaches goal, you lose a life & remove it.
So let's address every single one of these steps, and how I'd implement them:
Spawn any number of ants, in random position
Spawning requires 2 things:
A prefab
Usage of Instantiate()
If you don't know how to create a prefab, or what it is, I suggest googling around until you understand. In short, it's an instance of a GameObject saved to disk. You do this by simply dragging a GameObject to a folder in the inspector's project view.
public GameObject antPrefab;
GameObject SpawnAnt(Vector2 position) {
return Instantiate<GameObject>(antPrefab, position, Quaternion.identity);
}
Random position
How I like doing spawn positions is by declaring a spawn area GameObject, which you can move around in the editor, and specifying the size as a serialized field:
[Range(1f, 10f)] // Gives you a slider to drag between 1 and 10 for this variable
public float spawnAreaRadius;
public Transform spawnArea;
void Vector2 GetRandomSpawnPosition() {
var spawnAreaCenter = spawnArea.position;
var spawnRandomX = Random.Range(-spawnAreaRadius, spawnAreaRadius);
var spawnRandomY = Random.Range(-spawnAreaRadius, spawnAreaRadius);
return new Vector2(spawnRandomX, spawnRandomY);
}
And regarding spawning multiple, you'd probably want to put up some event/timer to spawn and increase the ants to make it progressively harder:
Call this when you want to spawn a certain amount of ants in a random pattern around your spawn position:
void SpawnAnts(int num) {
for (int i = 0; i < num; i++) {
var pos = GetRandomSpawnPosition();
SpawnAnt(pos);
}
}
Ant movement & lifecycle
Instead of looping over all ants and moving them with an overhead controller, which may be the optimal solution, for the sake of simplicity I'd add a script to the antPrefab that contains the ants:
(This component requires a rigidbody & collider)
void Update() {
// Move ant towards goal
}
void OnMouseDown() {
Destroy();
}
This will also give you a chance to easily give different ants different speeds, etc. Make each ant's AI a bit unique with far less effort than if they were grouped together.
Colliding with goal
Define an area which is the ant's goal by placing a Trigger Collider in your world. Add your existing script to it and add a method for detecting collisions:
void OnTriggerEnter2D(Collider2D col) {
if (col.tag == "ant") {
lives--;
Destroy(col.gameObject);
}
}
Summary
Some of these things you already solved in your way (such as generateX()), I wanted to give you some insight in how I'd personally tackle your code. You should evaluate which parts you'd want to use.
Disclaimer: This achieves your requirements, but leaves you with some other limitations, such as adding points when clicking an ant requires you to, probably, call some singleton point manager from the ant, rather than just detecting it in the same controller, which also would handle points.
I am building an animation with lots of effects and animation in a website. I am trying to optimize the efficiency of those animations since some of them are a little complex to low CPU/RAM devices. The animations are not smooth as I want as you can see here https://www.empresasite.com.br
So I realize in many parts of my code I do this:
var x = 38; //this value changes every 50ms
document.getElementById("a").style.left = document.getElementById("b").style.left = document.getElementById("c").style.left = document.getElementById("d").style.left = document.getElementById("e").style.left = x + "px";
Actually it's a simplification above, I run the code above with at least 13 elements a = b = c = d .... m = x; and at least with 4 properties (left, height, box-shadow and background-color).
So I was wondering if there is any better alternative to assign the same value to multiple elements/objects at once?
Maybe the code below would be faster? I used it but I didnt see a significant improvement in animation, maybe I should have seen it?
var x = 38;
x = x + "px";
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
document.getElementById("c").style.left = x;
document.getElementById("d").style.left = x;
document.getElementById("e").style.left = x;
I think the code above should be faster right? I say this cause every element updates its own property (left) retrieving the value from "x". In the first example I gave MAYBE javascript is assigning the value of the previous element in the chain of "=" sign so it has to assign "x" to the first element then assign the value of the first element to the second... go on.
Do you know exactly what jquery does when I use this:
$(".elements").css({left:x});
Does it use some optimization?
You could increase performance no-end by using translate instead of modifying position.
Using the jQuery variation you asked will not make any difference, as you are still modifying position left.
After playing around with most of the javascript benchmarking tools online I came up to this conclusion:
1) Jquery is the faster method of all native js solutions I used. Maybe Jquery uses some sort of optimization when you apply the same property to lots of elements at once! So you should rely on $(".class").css("left",x) to apply the x value to left property for hundreds of elements and it will be the faster solution;
2) The second solution is apply x individually TO EACH element. Example:
var x = 38;
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
3) The worst solution was actually the one I was using in the website that I was facing not smooth animations. So avoid this:
document.getElementById("a").style.left = document.getElementById("b").style.left = ... = ... = x;
The difference from the 1st solution to the 3rd is really noticeable. You can check it in the links below (pay special attention to the animation at the top):
1) https://www.empresasite.com.br/?q=principal&before -> this is using the 3rd solution
2) https://www.empresasite.com.br/?q=principal -> this is using the 1st solution
In a computer with lots of resources you may not see a difference but if you run this in a computer with 4GB of RAM or less you will see a big impact!
Hope this helps anyone that does not have smooth animations!
I'm creating a side-scrolling space-shooter in javascript. So far everything seems to be working well. However, there is an odd bug in the canvas rendering that I can't quite figure out (and is difficult to describe, so bear with me!)
I have a player that can shoot projectiles by clicking the left mouse button. When the projectile first leaves the player, there appears to be two of them for a brief second, until they eventually merge in to the one projectile. I'm not creating two, so this seems like an optical illusion (this is most evident if you fire a few projectiles in quick succession).
The really odd thing is, when I try and capture a screenshot of this happening, all looks fine. Can anyone figure out what's going on?
Player code including projectiles (full code in fiddle);
var Player = (function () {
// ------------------------------------------------------------------------------------------------
// PLAYER VARIABLES
// ------------------------------------------------------------------------------------------------
var w = 50;
var h = 50;
var x = 0;
var y = 0;
var projectiles = [];
// ------------------------------------------------------------------------------------------------
// BIND EVENTS TO THE GLOBAL CANVAS
// ------------------------------------------------------------------------------------------------
Canvas.bindEvent('mousemove', function (e) {
y = (e.pageY - Canvas.element.getBoundingClientRect().top) - (h / 2);
});
Canvas.bindEvent('click', function () {
createProjectile(50, (y + (h / 2)) - 10);
});
// ------------------------------------------------------------------------------------------------
// FUNCTIONS
// ------------------------------------------------------------------------------------------------
var createProjectile = function (x, y) {
projectiles.push({
x: x,
y: y
})
};
var update = function () {
for (var p = projectiles.length - 1; p >= 0; p--) {
projectiles[p].x += 10;
if (projectiles[p].x > Canvas.element.width)projectiles.splice(p, 1);
}
};
var render = function () {
Canvas.context.fillStyle = 'white';
Canvas.context.fillRect(x, y, w, h);
for (var p = 0; p < projectiles.length; p++) {
Canvas.context.fillStyle = 'red';
Canvas.context.fillRect(projectiles[p].x, projectiles[p].y, 5, 5);
}
};
// ------------------------------------------------------------------------------------------------
// Exposed Variables and Functions
// ------------------------------------------------------------------------------------------------
return {
update: update,
render: render
}
})();
Js Fiddle Demo HERE: https://jsfiddle.net/oqz204bj/
EDIT
Based on #Pimskie's answer, It does indeed seem like an optical illusion - so my question now becomes, how could I reduce this effect? I plan on implementing a feature in the future that allows the player to switch weapons (where some of them would **actually* fire multiple projectiles) but I don't want this effect to remain for fear of confusion.
yes it is an optical illusion. The reason it looks like there multiple squares when first fired is because your eyes are focused on the big static ship square. Once your eye starts to follow the movement path, then it looks more like a fluid square moving instead of a square being redrawn 60 or 30 times per second. hold a piece of paper or your hand up to your screen covering the left half of it. Focus on the piece of paper and fire a few shots. You'll notice that the shots seem to appear multiple, the same as when just fired. It's a matter of your mind seeing 3 different frames as the same one.
requestAnimationFrame depends on the frame rate of your browser and computer. In most cases that's 60fps. 60 to 70fps is the limit of most monitors, and so it doesn't make sense to try and go above that. HOWEVER you can create the illusion of a more fluid movement by having a trailing tracer effect on your projectiles. That would involve having 2 or 3 extra squares created behind each projectile that have less and less opacity.
My best guess it's an optical illusion indeed.
Check this updated fiddle: https://jsfiddle.net/oqz204bj/1/
I removed one requestAnimationFrame and replaced a other with a very slow setInterval, just for demonstration. You can see only one bullet is created.
As stated above, I am trying to build a simple game, but I can't seem to get the enemies moving correctly. The game is a Minecraft style block-based game. The code I am using so far makes the enemy start following me when I get within a certain distance and stop following once I get a certain distance away.
The problem I am having with this script is that the enemy sort of floats off into the distance when I escape him. More importantly, I cannot for the life of me get the enemy to jump. I know that I should be using two Raycasts for this: one to detect a block in front which will make the enemy jump and another to detect below the enemy and let him fall to the level below if there is no collier at his feet? I have no idea how to go about implementing this and some help would be greatly appreciated.
The code I have thus far can be seen below:
var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var rotationSpeed = 3; //speed of turning
var range : float=10f;
var range2 : float=10f;
var stop : float=0;
var myTransform : Transform; //current transform data of this enemy
function Awake() {
myTransform = transform; //cache transform data for easy access/preformance
}
function Start() {
target = GameObject.FindWithTag("1Player").transform; //target the player
}
function Update () {
//rotate to look at the player
var distance = Vector3.Distance(myTransform.position, target.position);
if (distance<=range2 && distance>=range) {
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position),
rotationSpeed*Time.deltaTime);
} else if (distance <= range && distance > stop) {
//move towards the player
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position),
rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
} else if (distance <= stop) {
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position),
rotationSpeed*Time.deltaTime);
}
//lock rotation on x and y axis to zero
myTransform.eulerAngles = new Vector3(0f, myTransform.eulerAngles.y, 0);
}
The design can change really a lot. It depends how clever AI do you want ? And how realistic it should be. Firstly you should check distance and as I saw you did that. The question is what if there is a wall or something ? Maybe they are so close to each other but there is a wall between them. This is why you need raycast. So you send a raycast from enemy to player. If there is no obstacle between them AI can decide that "aye I should come after you". But here is another problem for being realistic. What if its not looking to you ? If the AI can spot the player when it looks somewhere else, it is not that cool right ? So you also check if the player is in front of the AI. Maybe we can do it like this :
var heading = target.position - transform.position;
var dot: float = Vector3.Dot(heading, transform.forward);
so if dot is -1 we can say it is directly behind and +1 means in front of it. Well, now another problem. If player should be in front of the AI to be spotted then AI can not stand right ? It should move and turn around randomly. We can work on that later if you gonan need it.
Now another problem what if you hide after an object ? What it should do ? I mean when you are running if something came between you and AI, since raycast will fail it will stop following you right ? What we can do for it ? My sugesstion store the last position of the player which AI saw. And at least go to there to check if AI can find the player there. If it cant, it may keep moving randomly. By doing this it will looks more realistic I believe.
Edit: Lol I realised that i just improved you design and forgot to answer what exactly you asked.
Firstly AI shoudl know if it is grounded or not. What we need to know first distance to ground when we send raycast we gonan need it.
var distanceToGround = GetComponent<Collider>().bounds.extents.y;
function boolean isGrounded(){
return Physics.Raycast(transform.position, -Vector3.up, distanceToGround + 0, 1);
}
AI should send a raycast not from its head more like below the knees. Not send it too far away just a little distance will be enough. It is just to understand it there is an obstacle. And also send another raycast but this time now below the knees. From the jump height. And if it dont hit anything we can decide that there is an obstacle (first raycast says that) but AI can jump over it (second raycast says that). After deciding it, if AI also grounded that means it can jump and pass trough the obstacle.
Lets say this is the part 1. If you want me to keep telling, I can write another part for you. Have a nice day !
I'd like to add acceleration in javascript. For instance, if I press and hold a button, then the object moves accelerated in the chosen direction.
Could someone suggest please, how to start this one? Should I log the time of the keypress? If yes, how can I do this?
Thank you
You should do dome research on Kinematics.
You can do this with a simple loop that models the correspondence between position, velocity and acceleration.
I've made a simple example (using jQuery for accessing DOM/CSS):
var position = 0;
var velocity = 0;
var acceleration = 0.1;
var $thing = $("#thing");
var loop = function () {
$thing.css("left", position + "px");
position = position + velocity;
velocity = velocity + acceleration;
}
window.setInterval(loop, 100);
You can run it here: http://jsfiddle.net/QAn3Z/
Now you just need to add keypress detection.
This should get you started. Come back with more specific questions or problems, they will be less downvoted than "how should I begin" ;-)