Sprite Component exits screen in flame flutter - flutter

I am completely new to flame and game development, I know with camera and viewpoint you can control the components but my component exits the screen and I don't know how to stop it from moving forward when it reaches the screen end.
Any idea how?

You don't want to control how your SpriteComponents move with the camera, the camera moves what you are looking at in the "world" and you want to move your component in the world.
If you don't move the camera then the solution can be to just look at whether the component is still within the screen by using a ScreenHitbox and the CollisionDetection system. (You could also just check the bounding box against the screen size).
Something like this, where it just moves back to the position it was in before colliding with the screen, should work:
class YourGame extends FlameGame with HasCollisionDetection {
Future<void> onLoad async {
add(ScreenHitbox());
}
...
}
class YourComponent extends SpriteComponent {
final Vector2 lastPosition = Vector2.zero();
#override
Future<void> onLoad() async {
...
// Adds a hitbox that covers the size of your component,
// so make sure that you have the size set.
add(RectangleHitbox());
}
...
#override
void update(double dt) {
lastPosition.setFrom(position);
// Update your position etc here
}
#override
void onBeginCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
position = lastPosition;
}
}

Related

Warning when calling IsPointerOverGameObject after updating Unity; is there an alternative?

I have an InputAction callback where I am recording the position where the player clicks the screen, but only if the click is not over a UI element. Here's my code
private void OnPress(InputAction.CallbackContext context)
{
if (!EventSystem.current.IsPointerOverGameObject())
{
this.pressPosition = Mouse.current.position.ReadValue();
}
}
This has been working correctly. However, I recently updated my version of Unity, and now I'm getting this warning every time I click somewhere in my game:
Calling IsPointerOverGameObject() from within event processing (such as from InputAction callbacks)
will not work as expected; it will query UI state from the last frame
According to the changelog, this warning was added with an update to the input system.
Is there a way to figure out whether the mouse was over the UI when the player clicks the screen without getting this warning?
how I solved it was by moving just that piece of logic to an Unity's Update function:
private void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
if (EventSystem.current.IsPointerOverGameObject(PointerInputModule.kMouseLeftId))
// was pressed on GUI
else
// was pressed outside GUI
}
}
You can still keep using the inputsystem, i.e. when cancelled:
private void OnPress(InputAction.CallbackContext context)
{
if (context.canceled)
// Left mouse is no longer pressed. You can do something within the input system notification.
}
private bool pressControl = false;
private void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
pressControl =!EventSystem.current.IsPointerOverGameObject(PointerInputModule.kMouseLeftId);
}
void selector(InputAction.CallbackContext context)
{
if (!pressControl) return;
pressControl = false;
Vector3 position = new Vector3(mausePositionEvent.ReadValue<Vector2>().x, mausePositionEvent.ReadValue<Vector2>().y, 0);
Ray ray = Camera.main.ScreenPointToRay(position);
RaycastHit hit;
if (!Physics.Raycast(ray, out hit)) return;
}

How to move a Vector2 using PositionComponent with Flame/Flutter?

I am trying to move a Vector2's x position, the update is being called, the x value is changing but the white square component does not move, what am I missing?
i am using flame 1.0.0-releasecandidate.11.
import 'dart:ui';
import 'package:flame/components.dart';
import 'package:flame/palette.dart';
class PlayerComponent extends PositionComponent {
static const squareSize = 128.0;
static Paint white = BasicPalette.white.paint();
#override
void render(Canvas canvas) {
canvas.drawRect(size.toRect(), white);
super.render(canvas);
}
#override
void update(double dt) {
x += 10 * dt;
print(x);
super.update(dt);
}
#override
void onMount() {
super.onMount();
size.setValues(squareSize, squareSize);
anchor = Anchor.center;
}
}
class AnimalVillageGame extends BaseGame {
#override
Future<void> onLoad() async {
add(PlayerComponent()
..x = 100
..y = 100
);
}
}
You render method renders the size as a zero-bound rectangle, size.toRect() returns a Rect at the position 0,0.
Instead you can use the toRect method from the PositionComponent class:
#override
void render(Canvas canvas) {
canvas.drawRect(toRect(), white);
super.render(canvas);
}
This method returns the rect of the component, based on the x, y position and the size.
Edit:
As mentioned by spydon, the super.render is called after the rendering to the canvas, it would be better to call the super method first as it will automatically handle things like translation, rotation, etc for you.
It prepares the canvas for your own rendering.

Player's jumping compromised after reloading the scene in Unity

First of all, please don't get too technical: I've only been studying Unity coding for two months and I'm not a programmer in general! I'm a total beginner! :-)
So, I'm building a game where you control a ball on a treadmill avoiding endless spawning obstacles by shifting left-right and jumping.
I set up a restart function after game over with SceneManager.LoadScene method, it works, but after reloading the jumping function gets compromised: it looks like there's an invisible wall above the player blocking its jumps. And it also looks like it's an "additive" issue: if I die and restart again, the player jumps even less, until it just doesn't jump at all. The other functions seem fine.
Any idea why that happens?
public class PlayerController : MonoBehaviour
//Jump code:
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && isOnLane)
{
Jump();
}
}
void Jump()
{
playerRb.AddForce(Vector3.up * forceMult, ForceMode.Impulse);
isOnLane = false;
}
private void OnCollisionEnter(Collision other)
{
//checks if player is touching the ground
if (other.gameObject.CompareTag("Lane"))
{
isOnLane = true;
}
}
Restart code:
public class GameManager : MonoBehaviour
//restart game by clicking Restart Button
public void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
Thanks!
The problem is that additive scene loading is being used when there is only a single scene. It would be good to break these up into 2 scenes:
A scene for GameManager & the Player object
A scene for the level itself which is being reloaded
This way the GameManager is not being reloaded and the player is not being reloaded. Upon reload you need to "reset" variables for the player back to 0 and move him to a starting position.
RestartGame needs some logic to reset the player and his physics.
public void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
playerController.playerRb.velocity = Vector3.zero;
playerController.playerRb.angularVelocity = Vector3.zero;
playerTransform.position = spawnLocation.tranform.position;
}
You probably want to unload the scene, wait for 1 frame, and then load the scene. This way variables in the scene get reset properly.
public void RestartGame()
{
SceneManager.UnloadScene(scene);
playerController.playerRb.isKinematic = true; // Try setting kinematic between scenes
StartCoroutine(RestartLoad());
}
private IEnumerator RestartLoad()
{
yield return new WaitForEndOfFrame();
// Reset the player here
SceneManager.LoadScene(scene);
playerController.playerRb.isKinematic = false; // Player can use physics again
}

Physics OverlapSphere does not detect Collision

I wanted to create an collider on my players sword, that if he attacks that he would detect and via an animation event turn off/on an gameobject called (Damage Point) who was an script attached that would subtract the enemys health.
But somewhere it does not detect correctly. I tried to add the OnDrawGizmos function to see my sphere collider but even after making it bigger it does not detect.
The most strange thing about my issue is that im using the same code for my monster chest and my fantasy player, but for the chest it works but for the player it does not.
I created a class called PlayerDamage that is attached on an empty gameobject to the tip of my sword.
{
public class PlayerDamage : MonoBehaviour
public int damageAmount = 2;
public LayerMask enemyLayer;
void Update()
{
Collider[] hits = Physics.OverlapSphere(transform.position, 1.7f, enemyLayer);
if (hits.Length > 0)
{
if (hits[0].gameObject.tag == MyTags.ENEMY_TAG)
{
print("COLLIDED WITH ENEMY");
}
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, 1.7f);
}
In another script called PlayerScript that is attached directly to the player I have a function called Attack:
void Attack()
{
if (Input.GetKeyDown(KeyCode.K))
{
if (!anim.GetCurrentAnimatorStateInfo(0).IsName(MyTags.ATTACK_ANIMATION) || !anim.GetCurrentAnimatorStateInfo(0).IsName(MyTags.RUN_ATTACK_ANIMATION))
{
anim.SetTrigger(MyTags.ATTACK_TRIGGER);
}
}
}
Also in the PlayerScript class there are two functions called ActivateDamagePoint and DeactivateDamagePoint, these are assigned to animation events for the attack animations.
void ActivateDamagePoint()
{
damagePoint.SetActive(true);
}
void DeactivateDamagePoint()
{
damagePoint.SetActive(false);
}
I double checked that everything is on his layer and that the tags are okay, but that did not solve my problem.
Like I said before for the chest I use the same code and it works, but unfortunately it does not work with my player. I also have the Activate and Deactivate DamagePoint functions in there and these are also called by the animation event for my chest attack animation.
Okay after 1hour of debugging I finnaly found the solution:
It was in the MyTags class (a helper class for all the string variables), the error was:
public static string ENEMY_TAG = "Enemey";
instead of:
public static string ENEMY_TAG = "Enemy";

Google Glass: Not all axes seem to work using Accelerometer

I'm trying to make a simple glassware app that displays the accelerometer data on the screen. The code I am posting works on my Android phone, but when I use it on google glass, only the Y axis seems to work correctly (looking up and down).
When I say the Y axis, it's actually the third array entry from the SensorEvent event.values[] array (instead of the second array entry - see code).
All TextViews DO display a float value similar to how they appear on my android phone, but they just don't change by much (around .1 to .2) when moving my head.
public class SensorActivity extends Activity implements SensorEventListener {
SensorManager mSensorManager;
mAccel;
TextView tvx, tvy, tvz;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
tvx = (TextView) findViewById(R.id.tvx2);
tvy = (TextView) findViewById(R.id.tvy2);
tvz = (TextView) findViewById(R.id.tvz2);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccel = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccel, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause(){
super.onPause();
mSensorManager.unregisterListener(this);
}
#Override
protected void onResume(){
super.onResume();
mSensorManager.registerListener(this, mAccel, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
tvx.setText(Float.toString(x));
tvy.setText(Float.toString(y));
tvz.setText(Float.toString(z));
}
}
The Glass Documentation pretty much points to the Android documentation, so I am assuming they should be the same.
Any insight would be greatly appreciated.
**** NEW UPDATE ****
Now, all of a sudden. The Y-axis is reading the Y-direction (and the Z-axis is too). Main problem with that is that the Y-axis reading starts at value "9" and goes to "0" in either direction (no negative direction) so determining where the user is looking is an issue. I am aware I could call the Z-axis the Y-axis, but that would just be masking a different issue.
It turns out that the X-axis is registering head tilt and NOT head turn (which is not in accordance with the documentation). I haven't found any documentation pertaining to calibrating the accelerometer (if that's even possible).