I already tried to clamp it with mathf or hardocding it, but it didnt help either, it just slips trough, every time I rotate the camera on the edge of the map (min/max hsp - min/max vsp) the given edges of the terrain.
I'm out of ideas and searched days for a similar problem in hope to see my mistake and now I'm here. Hopefully someone can help me and show me the mistake I made. I want to learn so badly. you can see the code I used here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovementScript : MonoBehaviour
{
float speed = 1f;
float zoomSpeed = 10f;
float rotateSpeed = 50f;
float maxHeight = 200f;
float minHeight = 20f;
float minHsp = 10f;
float maxHsp = 750f;
float minVsp = 10f;
float maxVsp = 750f;
Vector2 p1;
Vector2 p2;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.LeftShift))
{
speed = 1f;
zoomSpeed = 2000f;
}
else
{
speed = 0.5f;
zoomSpeed = 1550f;
}
float hsp = transform.position.y * speed * Input.GetAxis("Horizontal") * Time.deltaTime;
float vsp = transform.position.y * speed * Input.GetAxis("Vertical") * Time.deltaTime;
float scrollSP = Mathf.Log(transform.position.y) * -zoomSpeed * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime;
if ((transform.position.y >= maxHeight) && (scrollSP > 0))
{
scrollSP = 0;
}
else if ((transform.position.y <= minHeight) && (scrollSP <0))
{
scrollSP = 0;
}
if((transform.position.y + scrollSP) > maxHeight)
{
scrollSP = maxHeight - transform.position.y;
}
else if((transform.position.y + scrollSP) < minHeight)
{
scrollSP = minHeight - transform.position.y;
}
if ((transform.position.x >= maxHsp) && (hsp > 0))
{
hsp = 0;
}
else if ((transform.position.x <= minHsp) && (hsp < 0))
{
hsp = 0;
}
if ((transform.position.x + hsp) > maxHsp)
{
hsp = maxHsp - transform.position.x;
}
else if ((transform.position.x + hsp) < minHsp)
{
hsp = minHsp - transform.position.x;
}
if ((transform.position.z >= maxVsp) && (vsp > 0))
{
vsp = 0;
}
else if ((transform.position.z <= minVsp) && (vsp < 0))
{
vsp = 0;
}
if ((transform.position.z + vsp) > maxVsp)
{
vsp = maxVsp - transform.position.z;
}
else if ((transform.position.z + vsp) < minVsp)
{
vsp = minVsp - transform.position.z;
}
Vector3 verticalMove = new Vector3(0,scrollSP,0);
Vector3 lateralMove = hsp * transform.right;
Vector3 forwardMove = transform.forward;
forwardMove.y = 0;
forwardMove.Normalize();
forwardMove *= vsp;
Vector3 move = verticalMove + lateralMove + forwardMove;
transform.position += move;
getCameraRotation();
}
void getCameraRotation()
{
if(Input.GetMouseButtonDown(2))
{
p1 = Input.mousePosition;
}
if(Input.GetMouseButton(2))
{
p2 = Input.mousePosition;
float dx = (p2 - p1).x * rotateSpeed * Time.deltaTime;
float dy = (p2 - p1).y * rotateSpeed * Time.deltaTime;
transform.rotation *= Quaternion.Euler(new Vector3(0,dx,0));
transform.GetChild(0).transform.rotation *= Quaternion.Euler(new Vector3(-dy,0,0));
p1 = p2;
}
}
}
THIS IS ALL IN THE STEP EVENT.
I am currently trying to create my first state machine for some enemy AI. Being very new to gml and gamemaker studio 2, my code is very basic as I do not know how to implement built in functions.
In 1 of my states, the rush state, the enemy is supposed to chase the player. I do this by creating some conditions, if the player is to the left of the enemy, the enemy will run left. If the player is to the right, the enemy will run right. This in theory is what I have coded but when I get in game, sometimes it will work, but then spasm and go the other way.
If my character is in the circle, it doesn't run towards the player but instead away. This does not change if I reverse the conditions.
case behaviour.rush:
{
//radius in square
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
//direction to face player
if (behaviourState == behaviour.rush && playerObject.x >. warriorx) hsp = -4;
else if (behaviourState == behaviour.rush &&
playerObject.x <= warriorx) hsp = 4;
x = x + hsp;
}
if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.idle;
}
}
My full code:
image_speed = 1;
vsp = vsp+grv;
Print(behaviourState);
if (hsp > 0) image_xscale = 3; else if (hsp < 0) image_xscale = -3;
//animation
if (behaviourState == behaviour.idle) sprite_index = tikiAxeWarriorIdle;
if (hsp == 2 || hsp == -2)sprite_index = tikiAxeWarriorWalk;
if (hsp == 4 || hsp == -4) sprite_index = tikiAxeWarriorRush;
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
Print("in circle");
}
Print(hsp);
switch(behaviourState)
{
case behaviour.idle:
{
//stand still
if (alarm[1] <= 0) alarm[1] = room_speed * 4;
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.rush;
}
}
case behaviour.wander:
{
if (alarm[0] <= 0) alarm[0] = room_speed * 3;
//move
if (!place_meeting(x + hsp,y,wallObject))
{
x = x + hsp;
}
if (place_meeting(x + hsp,y,wallObject))//checking frame before.
{
hsp = -hsp;
}
//check for behaviour.rush.
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.rush;
}
}
case behaviour.rush:
{
//radius in square
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
//direction to face player
if (behaviourState == behaviour.rush && playerObject.x > warriorx) hsp = -4;
else if (behaviourState == behaviour.rush && playerObject.x <= warriorx) hsp = 4;
x = x + hsp;
}
if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.idle;
}
}
case behaviour.attack:
{
//attack.
//if player is hit, he dies.
}
}
The expected result is for the enemy to "rush" towards my player position and when over stepped, to face the other way. If my player leaves the circle, it should go back to the idle state.
hsp = -hsp sounds very sensitive to the spasm. and since it's affect the hsp as whole, it'll also affect the place_meeting(x + hsp,y,wallObject) part.
I don't know the solution right away, but I think you should take a look at that section.
I also personally prefer to split your current hsp in two variables: the direction and speed, where the direction is a value of 1 or -1 and the speed is like hsp, but returns a positive value. And then combine them using speed * direction.
That way, you can calculate the speed without taking direction into account, and vice versa. Which may also solve the conflict you're currently having.
With switch statements, I believe you need to add "break;" in between each Case.
The YoYo documentation here has some good information on switch statements. Now this might not enable your code to run exactly as you're hoping, but it will get you one bug less towards your goal.
The pertinent part of the link states:
"...execution continues after the first case statement with the correct value, until a break statement is encountered....the break is not required, and if there is no break statement the execution simply continues with the code for the next case statement".
So essentially, without a break statement, the code will start at the case block matching the current value, and then run through the code of the all cases below it until it hits a "break;".
Here's what your code would look like with the "break;" added in to the correct spots.
image_speed = 1;
vsp = vsp+grv;
Print(behaviourState);
if (hsp > 0) image_xscale = 3; else if (hsp < 0) image_xscale = -3;
//animation
if (behaviourState == behaviour.idle) sprite_index = tikiAxeWarriorIdle;
if (hsp == 2 || hsp == -2)sprite_index = tikiAxeWarriorWalk;
if (hsp == 4 || hsp == -4) sprite_index = tikiAxeWarriorRush;
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
Print("in circle");
}
Print(hsp);
switch(behaviourState)
{
case behaviour.idle:
{
//stand still
if (alarm[1] <= 0) alarm[1] = room_speed * 4;
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.rush;
}
}
break;
case behaviour.wander:
{
if (alarm[0] <= 0) alarm[0] = room_speed * 3;
//move
if (!place_meeting(x + hsp,y,wallObject))
{
x = x + hsp;
}
if (place_meeting(x + hsp,y,wallObject))//checking frame before.
{
hsp = -hsp;
}
//check for behaviour.rush.
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.rush;
}
}
break;
case behaviour.rush:
{
//radius in square
if (point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
//direction to face player
if (behaviourState == behaviour.rush && playerObject.x > warriorx) hsp = -4;
else if (behaviourState == behaviour.rush && playerObject.x <= warriorx) hsp = 4;
x = x + hsp;
}
if (!point_in_circle(playerObject.x,playerObject.y,x,y,200))
{
behaviourState = behaviour.idle;
}
}
break;
case behaviour.attack:
{
//attack.
//if player is hit, he dies.
}
break;
}
Hope this helps!
Also, a quick tip!
One thing I noticed with your code is you repeat a couple expressions a few times. For readability sake, I recommend assigning these to a variable if possible. For example:
var in_circle = point_in_circle(playerObject.x,playerObject.y,x,y,200);
if in_circle {
}
if !in_circle {
}
I am trying to translate an old flash animation with animate. On the original flash animation the map image is draggable and zoomable but the map ´s borders always stick to the sides of the stage if you pan it or zoom it all the way.
On my test i grabbed some code that allows panning and zooming but the map crosses the stage boundaries if you pan all the way, in fact you can make the map dissapear of the stage.
I think there should be a way to draw like a secondary outer stage and not let the map image go beyond it.
This is the code I have.
var that = this;
var clickedX;
var clickedY;
var isDragging = false;
var friction = 0.85;
var speedX = 0;
var speedY = 0;
var mapOriginalX = this.map.x;
var mapOriginalY = this.map.y;
var mapNudge = 5;
var minScale = 0.25;
var maxScale = 3;
function onMouseWheel(e)
{
var delta;
if (e == window.event)
delta = -10 / window.event.wheelDeltaY;
else
delta = e.detail / 30;
var zoomFactor = delta;
scaleMap(zoomFactor);
}
function mouseDown(e)
{
clickedX = stage.mouseX;
clickedY = stage.mouseY;
isDragging = true;
console.log(stage.mouseX);
console.log(stage.mouseY);
}
function stageMouseUp(e)
{
isDragging = false;
}
function update(e)
{
if (isDragging)
{
speedX = stage.mouseX - clickedX;
speedY = stage.mouseY - clickedY;
}
speedX *= friction;
speedY *= friction;
// saber el tamaño actual del mapa en este punto.
that.map.x += speedX;
that.map.y += speedY;
console.log(that.map.y);
console.log(that.map.x);
clickedX = stage.mouseX;
clickedY = stage.mouseY;
//
}
function resetMap()
{
that.map.x = mapOriginalX;
that.map.y = mapOriginalY;
that.map.scaleX = that.map.scaleY = 1;
}
function zoomMap(e) //control visual
{
if (e.currentTarget == that.plusButton)
scaleMap(-0.1);
if (e.currentTarget == that.minusButton)
scaleMap(0.1);
}
function moveMap(e) //control visual
{
if (e.currentTarget == that.upButton)
speedY -= mapNudge;
else if (e.currentTarget == that.rightButton)
speedX += mapNudge;
else if (e.currentTarget == that.downButton)
speedY += mapNudge;
else if (e.currentTarget == that.leftButton)
speedX -= mapNudge;
}
function scaleMap(amount)
{
var map = that.map; // we will scale de map so this goes first.
map.scaleX -= amount; // same as map.scaleX = map.scaleX - amount
map.scaleY = map.scaleX;
if (map.scaleX < minScale)
map.scaleX = map.scaleY = minScale;
else if (map.scaleX > maxScale)
map.scaleX = map.scaleY = maxScale;
}
// listeners
this.map.on("mousedown", mouseDown.bind(this));
this.resetButton.on("click", resetMap.bind(this));
this.plusButton.on("click", zoomMap.bind(this));
this.minusButton.on("click", zoomMap.bind(this));
this.upButton.on("click", moveMap.bind(this));
this.rightButton.on("click", moveMap.bind(this));
this.downButton.on("click", moveMap.bind(this));
this.leftButton.on("click", moveMap.bind(this));
stage.on("stagemouseup", stageMouseUp.bind(this));
document.getElementById('canvas').addEventListener('mousewheel', onMouseWheel.bind(this));
document.getElementById('canvas').addEventListener('DOMMouseScroll', onMouseWheel.bind(this));
createjs.Ticker.addEventListener("tick", update.bind(this));
resetMap();
One trick I usually use is to create a "fence" procedure that checks bounds and corrects them. It will take some setup though.
To use this method, first set up these variables based on your own scene. Perhaps this is what you meant by defining a "second stage?"
var stageLeft = 0;
var stageRight = 500;
var stageTop = 0;
var stageBottom = 500;
this.map.setBounds(0,0,1462, 1047); // Set the values to match your map
var mapBounds = this.map.getBounds();
Then, add this procedure, or a variation of it based on how your map coordinates are set.
// procedure to correct the map x/y to fit the stage
function fenceMap() {
var map = that.map;
var ptTopLeft = map.localToGlobal(mapBounds.x,mapBounds.y);
var ptBotRight = map.localToGlobal(mapBounds.width,mapBounds.height);
if ((ptBotRight.x - ptTopLeft.x) > (stageRight-stageLeft)) {
if (ptTopLeft.x > stageLeft) {
map.x -= ptTopLeft.x - stageLeft;
speedX = 0;
} else if (ptBotRight.x < stageRight) {
map.x -= ptBotRight.x - stageRight;
speedX = 0;
}
}
if ((ptBotRight.y - ptTopLeft.y) > (stageBottom-stageTop)) {
if (ptTopLeft.y > stageTop) {
map.y -= ptTopLeft.y - stageTop;
speedY = 0;
} else if (ptBotRight.y < stageBottom) {
map.y -= ptBotRight.y - stageBottom;
speedY = 0;
}
}
}
Then, just add to the end of your update(), zoomMap(), moveMap(), and scaleMap() functions:
fenceMap();
I am looking to control an ROV by using either a PS4 controller or an Xbox 360 controller. I plan to do this by connecting the controller to a computer and then sending that to the ROV. A little background information on the project is, we have the controller up top, which sends it to the computer, and then we will send from the computer to an Arduino on the ROV via Ethernet.
I have learned that this is possible on the PS3 controller by using Processing because another team did it, but I am unfamiliar with that language and don't have a PS3 controller. However, I have a PS4 and Xbox 360 controller.
From what I have researched, SDL could be an option for this, but I am looking for advice from more experienced people than me.
My question got deleted by pissed mods, because it was "unrelated", but I asked the same. Anyway, I implemented my PS4 controller support with SFML like this. Other simple possibility would be SDL. XBox will be the same I guess. Have fun
Here some sample code..
sf::Joystick::update();
// Is joystick #0 connected?
m_bGamepadConnected = sf::Joystick::isConnected(0);
if(!m_bGamepadConnected) {
return;
}
// Does joystick #0 define a X axis?
m_bStickLX = sf::Joystick::hasAxis(0, sf::Joystick::X);
m_bStickLY = sf::Joystick::hasAxis(0, sf::Joystick::Y);
m_bStickRX = sf::Joystick::hasAxis(0, sf::Joystick::Z);
m_bStickRY = sf::Joystick::hasAxis(0, sf::Joystick::R);
m_bStickL2 = sf::Joystick::hasAxis(0, sf::Joystick::U);
m_bStickR2 = sf::Joystick::hasAxis(0, sf::Joystick::V);
m_tJoystick.start(5);
QObject::connect(&m_tJoystick, SIGNAL(timeout() ), this, SLOT(updateGamepad() ) );
And this may help you ..
sf::Joystick::update();
float fStickLX = 0;
float fStickLY = 0;
float fStickRX = 0;
float fStickRY = 0;
float fStickL2 = 0;
float fStickR2 = 0;
// What's the current position of the analog sticks
if(m_bStickLX) {
fStickLX = sf::Joystick::getAxisPosition(0, sf::Joystick::X) / 100;
}
if(m_bStickLY) {
fStickLY = sf::Joystick::getAxisPosition(0, sf::Joystick::Y) / 100;
}
if(m_bStickRX) {
fStickRX = sf::Joystick::getAxisPosition(0, sf::Joystick::Z) / 100;
}
if(m_bStickRY) {
fStickRY = sf::Joystick::getAxisPosition(0, sf::Joystick::R) / 100;
}
// R2 and L2
if(m_bStickL2) {
fStickL2 = sf::Joystick::getAxisPosition(0, sf::Joystick::U) + 100;
fStickL2 /= 200;
}
if(m_bStickR2) {
fStickR2 = sf::Joystick::getAxisPosition(0, sf::Joystick::V) + 100;
fStickR2 /= 200;
}
if(m_fStickLX != 0 || m_fStickLY != 0 || m_fStickRX != 0 || m_fStickRY != 0 || m_fStickL2 != fStickL2 || m_fStickR2 != fStickR2) {
m_bGamepadInUse = true;
} else {
m_bGamepadInUse = false;
}
m_fStickLX = fStickLX;
m_fStickLY = fStickLY;
m_fStickRX = fStickRX;
m_fStickRY = fStickRY;
m_fStickL2 = fStickL2;
m_fStickR2 = fStickR2;
m_bButLPressed = isButtonPressed(0, 0);
m_bButDPressed = isButtonPressed(0, 1);
m_bButRPressed = isButtonPressed(0, 2);
m_bButTPressed = isButtonPressed(0, 3);
//qDebug() << "m_bButDPressed pressed: " << m_bButDPressed;
static bool bArmToggle = false;
if(m_bButDPressed && !bArmToggle) {
m_bDeviceArmed = m_bDeviceArmed ? false : true;
bArmToggle = true;
qDebug() << "Device armed?: " << m_bDeviceArmed;
}
if(bArmToggle && !m_bButDPressed) {
bArmToggle = false;
}
I keep getting
Error #2006: The supplied index is out of bounds.
at flash.display::DisplayObjectContainer/getChildAt()
at Main/onFrame()
This is mostly referring to this part of my code
else if (comp) //if completion is true
{
var animation = char.getChildAt(2); //
if (animation.currentFrame == animation.totalFrames)
{
animation.stop();
addChild(end);
My animation that I am pulling at the second frame also isn't running at all, though I have checked the symbol and the frames within it, and it should work fine. I'm pretty new to code and this is what I have been taught so far.
This is the rest of my code here.
We are supposed to make a basic game where our character walks to a power up and does a power up animation, followed by an end game title.
package
{
import flash.display.MovieClip;
import fl.motion.easing.Back;
import flash.sampler.Sample;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends MovieClip
{
var bg:Background;
var b:Bubbles;
var b2:Bubbles;
var s:Seaweed;
var pressingRight:Boolean = false;
var pressingLeft:Boolean = false;
var comp:Boolean = false;
var speed:int = 10;
var char:Character;
var pu:PowerUp;
var hit:hit1
var end:EndGame;
public function Main()
{
bg = new Background;
addChild(bg);
char = new Character();
addChild(char);
char.x = stage.stageWidth/2;
char.y = 488;
b = new Bubbles();
addChild(b);
b2 = new Bubbles();
addChild(b2);
b2.y = +b2.height;
s = new Seaweed();
addChild(s);
pu = new PowerUp();
addChild(pu);
pu.x = 200;
pu.y = 450;
pu.height = 50;
pu.scaleX = pu.scaleY;
pu.gotoAndStop("SPIN");
hit = new hit1;
addChild(hit);
hit.x = char.x
hit.y = char.y - 50
end = new EndGame();
end.x = stage.stageWidth/2;
end.y = stage.stageHeight/2;
stage.addEventListener(Event.ENTER_FRAME, onFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
}//main()
public function onFrame(e:Event)
{
if (!comp)
//Bubble Movement
b.y -= 1;
b2.y -= 1;
if (b.y >= stage.stageHeight)
{
b.y = b2.y + bg.height;
}
else if (b2.y >= stage.stageHeight)
{
b2.y = b.y + b2.height;
}
//Background & Character Movement
if (pressingRight && char.x < stage.stageWidth/2)
{
char.x += speed * 0.4
}
else if (pressingRight == true && (bg.width + bg.x) > stage.stageWidth)
{
bg.x -= speed * 0.4;
s.x -= speed * 0.6;
pu.x -= speed * 0.4;
}
else if (pressingRight == true)
{
char.x += speed * 0.4;
}
if (pressingLeft == true && char.x > stage.stageWidth/2)
{
char.x -= speed * 0.4;
}
else if (pressingLeft == true && bg.x <0)
{
bg.x += speed * 0.4;
s.x += speed * 0.6;
pu.x += speed * 0.4;
}
else if (pressingLeft)
{
char.x -= speed * 0.4;
}
//Boundaries
if (char.x > stage.stageWidth)
{
char.x = stage.stageWidth;
}
else if (char.x < 0)
{
char.x = 0;
}
//Character Looking Directions
if (pressingLeft == true)
{
char.scaleX = -1;
hit.x = char.x
}
if (pressingRight == true)
{
char.scaleX = 1;
hit.x = char.x
}
//Character Movements
if (pressingRight || pressingLeft)
{
char.gotoAndStop("WALK");
}
else if (!pressingRight || !pressingLeft)
{
char.gotoAndStop("IDLE");
}
//Getting the Power up
if (pu.hitTestObject(hit))
{
char.gotoAndStop("POWER");
comp = true;
pu.gotoAndStop("GONE");
}
// !end
else if (comp) //if completion is true
{
var animation = char.getChildAt(2); //
if (animation.currentFrame == animation.totalFrames)
{
animation.stop();
addChild(end);
}
}//Comp
}//onFrame
public function keyPressed(k:KeyboardEvent)
{
if (k.keyCode == Keyboard.RIGHT)
{
pressingRight = true;
}
else if (k.keyCode == Keyboard.LEFT)
{
pressingLeft = true;
}
} // keyPressed()
public function keyReleased(k:KeyboardEvent)
{
if (k.keyCode == Keyboard.RIGHT)
{
pressingRight = false;
}
else if (k.keyCode == Keyboard.LEFT)
{
pressingLeft = false;
}
} // keyReleased()
}//public class()
}//package()
If you're using a language with zero-based indexing (where array indexes start at 0, not 1) Then this could be the problem.
Frame 1 would be at index [0] and frame 2 would be at index [1].
If you have 2 frames for example and try to access the frame at index[2] you are stepping beyond the bounds of your array and this is probably why you are getting that error message.