I`m making a 2d game based on levels in which, each level, you have three checkpoints in the score tracking bar. The player must reach the lowest checkpoint to be able to pass to the next level, but will get a bonus if he reaches the 2nd and 3rd checkpoints.
I tought on using a Slider as the scoring bar. My question is:
Is there a way to store a specific value of the Slider's bar in the Start method and Instantiate a marker prefab at that position? Here's an example:
The Max Value of the Slider at Level 1 is 100.
I want to Instantiate the first marker, with some padding in the y, in the 50`s position of the slider, the second in the 75 position and the third in the 100 position.
My current logic is that I need to, somehow, get the value I want and find his Transform, but I can`t find a way to code this, I have no idea how to get the position I want.
Here are some images to illustrate what i`m trying to do:
i would get the width attribute of the slider, then divide that by sliderMax, the result will be the the width of a single % on the slider. you can then add or subract multiple of this to get a percentages place on the bar.
example: slider.x=50
slider.width=200;
increment = slider.width/100; //this will result in two, giving you two pixels per percent.
so your 50 percent placement would be: sliderx+(increment*50);
keep in mind this is all pseudo code, designed to give you an idea of how to acheive your desired result
I found the solution!
Based on the insights i managed to do this:
void SpawnCheckPoint() {
mySlider.maxValue = gameLevel[currentLevel].maxValue; //Set the slider's Max Value to the max value of the level.
float sliderMaxValue = mySlider.maxValue;
float sliderWidth = slider.GetComponent<RectTransform>().sizeDelta.x; //Get the width of the Slider.
float zeroValue = slider.transform.position.x - (sliderWidth / 2); //Get the leftmost corner of the slider.
//Loop to Instantiate the 3 checkpoints.
for (int i = 0; i < gameLevel[currentLevel].values.Length; i++) {
float valueToIncrement = (gameLevel[currentLevel].values[i] / sliderMaxValue); //Get the % of the checkpoint based on the max value of the level.
float newPos = (sliderWidth * valueToIncrement); //New position in screen
//Instantiate the object as a child of the Slider
GameObject checkpoint = Instantiate(checkPoint, new Vector3(zeroValue + newPos - xPadding, slider.transform.position.y - yPadding, slider.transform.position.z),
Quaternion.identity, GameObject.FindGameObjectWithTag("Slider").transform);
}
}
It's probably not the best way to do what i want but it's working just fine.
Thank you all who tried to help me, your insights were very useful.
Related
I have a button that makes the MainCamera switch between being in the middle of several objects.
For example, there's the [StartPoint , CheckPoint , CheckPoint , EndPoint]
I want the camera to switch continuously across the checkpoints like the comma between the checkpoints. ^^
This code is the actual switching the position placing for the MainCamera (where the error might be)
public void SwitchCameraBetween(GameObject nextPoint, GameObject afterNextPoint)
{
Vector3 centerPoint = (afterNextPoint.transform.position - nextPoint.transform.position) / 2;
centerPoint.z = -10;
float cameraSize = (afterNextPoint.transform.position - nextPoint.transform.position).magnitude - nextPoint.transform.localScale.x;
mainCamera.transform.position = centerPoint;
mainCamera.orthographicSize = cameraSize / 3;
}
The camera switches perfect for the first 2 checkpoints (either StartPoint & EndPoint or StartPoint & CheckPoint) after the camera stays in same position or off by a couple values. I checked by using Debug.Log(); to see if the camera has the correct gameobjects between and it does so why does it not work?
The center point should be the average of all points, so you need to add your points, not subtract them, and then divide the result by the number of points included for the average.
center = sum(points) / count(points), so center = (a + b) / 2
Alternatively, you could use Vector3.Lerp(a, b, 0.5f) if you find that more readable, although technically this would be slower, since it's both a method call and more operations, unless the compiler is doing fancy things behind the scenes...
I'm trying to move a PictureBox diagonally in a game I'm making.
private void movebulletupright()
{
//this part is mainly for checking the action[![enter image description here][1]][1]
for (int k = bulletlistupright.Count - 1; k >= 0; k--)
{
bulletlistupright[k].Location.X++;
bulletlistupright[k].Location.Y++;
//This part is just basically meant to get rid of the bullet
//when it reaches the end of the screen
if (bulletlistupright[k].Left >= this.ClientSize.Height)
{
this.Controls.Remove(bulletlistupright[k]);
bulletlistupright.RemoveAt(k);
}
}
}
I'm using a timer to move the bullets. What I would like to do is move the bullet 5 pixel per tick (which is 1 millisecond). if you look at the attached picture below, what i'm trying to do is move those yellow bullet shaped in the corners diagonally.(i only have them there so i can represent where they spawn in). [1]: http://i.stack.imgur.com/wQc5l.png
Try to move in one go:
bulletlistupright[k].Location = new Point(
bulletlistupright[k].Location.X + 5, // 5 is X step
bulletlistupright[k].Location.Y + 5); // 5 is Y step
in order to prevent jitting (i.e. unwanted redrawing - first redrawing after X coordinate is changed, than after Y)
I'm not sure I understand your question, but if you are moving it 1 pixel in your code, to move it 5 pixels, you'd only need to do:
bulletlistupright[k].Location.X+=5;
bulletlistupright[k].Location.Y+=5;
If that's not what you are looking for, please be more clear in your question
I have an integer that updates itself from 0 - 599 which I'm trying to normalize and pass to another variable. My first integer value is just a single int. It isn't in a list or anything.
What I'm trying to do is tie in a color lerp time length based on the length of integer value. This integer value is iterating through a list of meshes to be displayed. It looks like this:
int meshNum;
public void AnimateMesh()
{
if(playAnim)
{
meshToChange.GetComponent<MeshFilter>().mesh = fluidMesh[meshNum];
if(meshNum < 599)
meshNum++;
else
meshNum = 0;
}
else
{
meshNum = 0;
}
}
And my lerp code for the color is this:
diffuse_Material.color = Color.Lerp(Color.blue, Color.red, speedCount);
What I'm wanting to change speedCount in my lerp method to a variable that is matched with the length of the animation. My lerp isn't always on screen, but the animation is, when I want the lerp to appear, I want to it be the same each time it appears no matter where the animation currently is.
Color.Lerp expects a parameter from 0 .. 1. The simplest way would be to simply give it (float)meshNum / 599f.
float number = (float)randomizedNumber / 599.0f;
since your max value is 599, anyway this color difference would'nt be noticed or event will be rounded since RGB has only 256 values for eash base color.
I have a player sprite and a spikes sprite. The spikes are facing down and about at head level with the player. I have set it so that if the right side of the player's rectangle goes into the spikes's rectangle, it stops moving. However, I want to set it up like this-
if (playerRect.Right == spikesRect.Left - 1)
{
speedRight = 0;
}
However, this does not work. The player can continue to go past it. The only way I can get it to work is if I do this-
if (playerRect.Right > spikesRect.Left)
{
speedRight = 0;
}
To clarify, the spikesRect.Left value is 350. I want it so that if playerRect.Right is equal to 349, to stop moving to the right. Thanks for any help, it's appreciated.
If you just want a basic collision, use:
if(playerRect.Intersects(spikesRect))
{
//handle collision
}
I recommend having a velocity and a direction variable instead of different variables for different direction's speeds, it means that you only have to change one variable if you want your character to change speed or direction.
The main problem is is that as your player is moving it is not always going to land on spot 349. as its moving it might move from 348 to 350. therefore it will never trigger when it's 349. What you could however do is.
int i = spikesRect.Left - playerRect.Right;
if ( i < 0 )
playerRect.X += i; //playerRect.X can be replaced by a position variable
When it reaches spot 351. 350 - 351 = -1 so since it is less than 0 it will be added to playerRect.X making playerRect.X moved back to where playerRect.Right is 350. That way it won't look as if your player is penetrating the spike.
I think that the issue is caused by some changes you make to speedRight or to playerRect somewhere in your game. So if you're using VisualStudio just set a breakpoint and check the speedRight and playerRect values.
Although there are a few changes you should make to your game. Firstly you should create a public field into the Player class of type Texture as for the Spike class, then create another field of type Vector2 which indicates the speed and the direction :
public class Player{
public Vector2 DirectionSpeed;
public Texture2D Texture;
//...
public Player(){
//initialize your fields
}
}
Then you can handle the collision by using the method Intersects():
if(player.Texture.Bounds.Intersects(spike.Bounds)){
player.DirectionSpeed = Vector.Zero;
}
If you are trying to handle the collisions with more than one object of type Spike, you have to create a List<Spike> and then iterate with a cicle the entire list:
foreach(Spike s in listSpikes){
if(player.Texture.Bounds.Intersects(s.Bounds)){
player.DirectionSpeed = Vector.Zero;
}
}
EDIT:
Moreover if speedRight doesn't equal 1 or a submultiple of spikesRect.Left - 1 it's obvious that by increasing the position with it playerRect.Right exceeds spikesRect.Left - 1. A solution could be:
if (playerRect.Right > spikesRect.Left - 1)
{
playerRect.Location = spikesRect.Left - playerRect.Width - 1;
speedRight = 0;
}
I am trying to write my own Game of Life, with my own set of rules. First 'concept', which I would like to apply, is socialization (which basicaly means if the cell wants to be alone or in a group with other cells). Data structure is 2-dimensional array (for now).
In order to be able to move a cell to/away from a group of another cells, I need to determine where to move it. The idea is, that I evaluate all the cells in the area (neighbours) and get a vector, which tells me where to move the cell. Size of the vector is 0 or 1 (don't move or move) and the angle is array of directions (up, down, right, left).
This is a image with representation of forces to a cell, like I imagined it (but reach could be more than 5):
Let's for example take this picture:
Forces from lower left neighbour: down (0), up (2), right (2), left (0)
Forces from right neighbour : down (0), up (0), right (0), left (2)
sum : down (0), up (2), right (0), left (0)
So the cell should go up.
I could write an algorithm with a lot of if statements and check all cells in the neighbourhood. Of course this algorithm would be easiest if the 'reach' parameter is set to 1 (first column on picture 1). But what if I change reach parameter to 10 for example? I would need to write an algorithm for each 'reach' parameter in advance... How can I avoid this (notice, that the force is growing potentialy (1, 2, 4, 8, 16, 32,...))? Can I use specific design pattern for this problem?
Also: the most important thing is not speed, but to be able to extend initial logic.
Things to take into consideration:
reach should be passed as a parameter
i would like to change function, which calculates force (potential, fibonacci)
a cell can go to a new place only if this new place is not populated
watch for corners (you can't evaluate right and top neighbours in top-right corner for example)
It should not be difficult to write your algorithm to search all of the cells within the reach distance of a particular cell C. Each cell that has an inhabitant would have a particular force of repulsion on cell C. This force of repulsion is based on the distance from the cell to cell C. In the example that you have given, that force of repulsion is based upon the L-1 distance and is 2^(reach-distance). Each repulsion force is then added together to create a cumulative force that dictates the direction in which to move the inhabitant in cell C.
You do not need to write an algorithm for each different reach. The magnitude of the force can be determined via a simple formula. If you change that formula to something else such as a Fibonacci number, you should still be able to calculate the magnitude as needed based upon the distance and the reach.
Here is some rough code written in pseudo-Java showing the basic ideas: http://codepad.org/K6zxnOAx
enum Direction {Left, Right, Up, Down, None};
Direction push(boolean board[][], int testX, int testY, int reach)
{
int xWeight = 0;
int yWeight = 0;
for (int xDist=-reach; xDist<=+reach; ++xDist)
{
for (int yDist=-reach; yDist<=+reach; ++yDist)
{
int normDist = abs(xDist) + abs(yDist);
if (0<normDist && normDist<reach)
{
int x = testX + xDist;
int y = testY + yDist;
if (0<=x && x<board.length && 0<=y && y<board[0].length)
{
if (board[x][y])
{
int force = getForceMagnitude(reach, normDist);
xWeight += sign(xDist) * force;
yWeight += sign(yDist) * force;
}
}
}
}
}
if (xWeight==0 && yWeight==0) return Direction.None;
if (abs(xWeight) > abs(yWeight))
{
return xWeight<0 ? Direction.Left : Direction.Right;
}
else
{
return yWeight<0 ? Direction.Up : Direction.Down;
}
}
int getForceMagnitude(int reach, int distance)
{
return 1<<(reach-distance);
}
Write a function to loop over the neighbors:
Use min/max to clamp the bounds of the matrix.
Use a for loop to loop over all neighbors.
Modify the for loop bounds to represent reach.
:
def CalculateForceOnCell(x, y):
force_on_x_y = [0,0,0,0]
for i in range(max(0, x-reach), min(WIDTH, x+reach)+1):
limited_reach = reach - abs(x-i)
for j in range(max(0, y - limited_reach), min(HEIGHT, y + limited_reach + 1)):
force_coefficient = limited_reach + 1
AddNeighborForce(force_on_x_y, (x, y), (i, j), force_coefficient)
return force_on_x_y