So I created a monster which I want to be consistently moving right and left between x= 156 and x = 501
Here's what i have done so far in my move() method:
public void move()
{
int left = 156;
int right = 501;
if (left <= x)
{
x++;
}
if (x >= 501)
{
x -= 1;
}
}
Then I call the method using a timer
private void tmr2_Tick(object sender, EventArgs e)
{
foreach (Monster m in monsters_)
{
m.move();
}
screen.Refresh();
}
This doesn't work. Could someone please help out.
Thanks
Beside coordinates X and Y the monster has to have one more property, let's call it Direction. When monster reaches one of the goals you change this Direction property, and only then you adjust the coordinates.
This might do the work for you
public class Monster
{
private const int MIN_X = 156;
private const int MAX_X = 501;
private int _x;
//your TL(probably) will tell you to use Enum
private bool _toLeft;
public Monster()
{
_toLeft = false;
_x = MIN_X;
}
public void Move()
{
if (_toLeft)
{
_x--;
}
else
{
_x++;
}
CheckEdges();
}
private void CheckEdges()
{
if (_x == MAX_X || _x == MIN_X)
_toLeft = !_toLeft;
}
}
You are missing the notion of direction in your code. You can do it in hundreds of ways so I'm not going to write the code here.
But once your x is equal to 501, you are decreasing its value by one, so on the next call its value is 500 therefore resetting it to 501 and so on. This is why it stops moving. You need to change direction on the edges, therefore increase or decrease X until you hit the other edge.
Related
I'm trying to figure out how to auto scroll a scrollview when a user drags an item to the edge of the screen. I'm really not getting the behavious I expect out of this code. Does anyone have an example or a technique that works?
I have this in my:
onDrag(View v, DragEvent e)
{
case DragAction.Location:
var currentPosition = (int)e.GetX();
var point = GetTouchPositionFromDragEvent(v, e);
System.Diagnostics.Debug.WriteLine($"DragAction.Location from {v.GetType()} => {currentPosition}");
System.Diagnostics.Debug.WriteLine($"DragAction.GLOBAL from {v.GetType()} => {point.X}");
if (point.X > App.AppScreenWidth - 50)
{
_hostScrollView.ScrollToAsync(_hostScrollView.ScrollX + 30, 0, true);
}
if (point.X < 50)
{
_hostScrollView.ScrollToAsync(_hostScrollView.ScrollX - 30, 0, true);
}
}
public static Point GetTouchPositionFromDragEvent(View item, DragEvent e)
{
Rect rItem = new Rect();
item.GetGlobalVisibleRect(rItem);
return new Point(rItem.Left + (int)Math.Round(e.GetX()), rItem.Top + (int)Math.Round(e.GetY()));
}
This also has the knock on effect of only scrolling in one direction strangely and also requires the user to keep moving the item in order to fire the events which leads me to think this is entirely the wrong place to be even trying to do this scrolling.
Any pointers or nudges in the right direction would be really appreciated.
In your Activity
public class MainActivity : AppCompatActivity, View.IOnDragListener,View.IOnScrollChangeListener
private int mScrollDistance;
ScrollView _hostScrollView= FindViewById<ScrollView>(Resource.Id.xxx);
_hostScrollView.SetOnScrollChangeListener(this);
public bool OnDrag(View v, DragEvent e)
{
var action = e.Action;
var scrollView = v as ScrollView;
switch (action)
{
case DragAction.Started:
break;
case DragAction.Location:
int y = Java.Lang.Math.Round(e.GetY());
int translatedY = y - mScrollDistance;
int threshold = 50;
// make a scrolling up due the y has passed the threshold
if (translatedY < threshold)
{
// make a scroll up by 30 px
scrollView.ScrollBy(0, -30);
}
// make a autoscrolling down due y has passed the 500 px border
if (translatedY + threshold > 500)
{
// make a scroll down by 30 px
scrollView.ScrollBy(0, 30);
}
break;
}
return true;
}
public void OnScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
var scrollView = v as ScrollView;
mScrollDistance = scrollView.ScrollY;
}
You could modify the logic as you want if I misunderstand your requirement .
I've been working on a game as a project and I've gotten round to introducing invincibility frames when the player takes a heart of damage. In this case I want it so that the player model flashes roughly once every 0.1 seconds and to have the invincibility last for 2 seconds.
I've written this code and I can't figure out why it isn't working. By the way using this code when the player takes damage they cannot take damage afterwards so something is really messed up (it isn't just the visual invincibility being an issue).
(Thank you)
private void loseHealth()
{
if (invinTimerCounter == 0)
{
curHealth -= 1;
invinTimerCounter = invinTimer;
invincibilityBlink();
}
}
private void invincibilityBlink()
{
for (int i = 0; i < 10; i++)
{
Invoke("spriteDisable", 1);
Invoke("spriteEnable", 1);
}
}
private void spriteEnable()
{
this.spriteRenderer.enabled = true;
}
private void spriteDisable()
{
this.spriteRenderer.enabled = false;
}
private void Update()
{
if (invinTimerCounter < 0)
{
invinTimerCounter -= Time.deltaTime;
}
}
In addition to jmalenfant's comment, I'd like to rewrite your invincibilityBlink() method to use a coroutine:
private IEnumerator invincibilityBlink()
{
for (int i = 0; i < 10; i++)
{
spriteDisable();
yield return new WaitForSeconds(0.1f);
spriteEnable();
yield return new WaitForSeconds(0.1f);
}
invincible = false;
}
Then, here:
if (!invincible)
{
curHealth -= 1;
invincible = true;
StartCoroutine(invincibilityBlink());
}
Oh, and we'll change that messy float to a boolean and let the coroutine handle it too, so if you decide to change the invincibility time, you only need to change things in one place.
I am currently creating a 2d platformer in monogame.
I created a block that, when hit by the player, starts dissapearing. When it dissapears, i draw a rectangle around it. Every Tile of the same type (BrittleTile) also starts dissapearing, untill the entire connected mob of BrittleTiles has dissapeared.
The problem is that for every BrittleTile that is destroyed, my game runs noticably slower, until it becomes a slideshow after 10 or so BrittleTiles destroyed. I have no idea as to what may cause this, i've been trying to ease the Update method of the class but nothing seems to help.
Any idea as to what may cause this?
class BrittleTile: Tile, IIncludeSound
{
public Rectangle DestroyedCheckRectangle;
private BrittleTile brittle;
private bool _isPlayed;
private bool _hasBroken;
private SoundEffect _sfxBreak;
private SoundEffectInstance _sfxiBreak;
private TimeSpan _breakTimer = new TimeSpan();
public Rectangle BrokenViewRectangle { get; set; }
private bool _isBreaking = false;
public BrittleTile(Texture2D texture, Rectangle baseViewRectangle, Rectangle brokenViewRectangle):base(texture, baseViewRectangle, true )
{
this.BrokenViewRectangle = brokenViewRectangle;
this.ViewRectangle = baseViewRectangle;
}
public void Update(GameTime gameTime, Hero hero, Entity[,] grid)
{
if (!this._hasBroken)
{
if (!this._isBreaking && !this._hasBroken && this.hasCollision)
_checkCollision(hero, grid);
if (this._isBreaking)
{
if (!this._isPlayed)
_sfxiBreak.Play();
this._isPlayed = true;
this._breakTimer += gameTime.ElapsedGameTime;
if (this._breakTimer.TotalMilliseconds < 250)
this.GhostMode(gameTime);
else
{
this._isBreaking = false;
this.hasCollision = false;
this._breakTimer -= this._breakTimer;
}
}
else
{
if (!this.hasCollision && this.DestroyedCheckRectangle.Width == 0)
{
this.DestroyedCheckRectangle.X = this.DestinationRectangle.X - 10;
this.DestroyedCheckRectangle.Y = this.DestinationRectangle.Y - 10;
this.DestroyedCheckRectangle.Height = this.DestinationRectangle.Height + 20;
this.DestroyedCheckRectangle.Width = this.DestinationRectangle.Width + 20;
this._hasBroken = true;
}
}
}
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.BrokenViewRectangle, Color.White);
if (this.hasCollision)
spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.ViewRectangle, Color.White * this.GhostDraw * 0.9f);
spriteBatch.Draw(this.Texture, DestroyedCheckRectangle, new Rectangle(1, 1, 1, 1), Color.Yellow);
Console.WriteLine(this.DestroyedCheckRectangle.X + ", " + this.DestroyedCheckRectangle.Y + ", " + this.DestroyedCheckRectangle.Width + ", " + this.DestroyedCheckRectangle.Height);
}
private void _checkCollision(Hero hero, Entity[,] grid)
{
if (this.DestinationRectangle.Intersects(hero.AttackHitBox))
{
this._isBreaking = true;
}
foreach (Shuriken star in hero.Stars)
{
if (this.DestinationRectangle.Intersects(star.DestinationRectangle))
this._isBreaking = true;
}
foreach (Entity entityObject in grid)
{
if (hasCollision && entityObject.GetType() == typeof(BrittleTile)){
brittle = entityObject.DeepCopy() as BrittleTile;
if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
this._isBreaking = true;
}
}
}
override public void LoadSounds(ContentManager content)
{
this._sfxBreak = content.Load<SoundEffect>("SFX/brittleBreak");
_sfxiBreak = _sfxBreak.CreateInstance();
_sfxiBreak.Volume = 0.2f;
}
}
First, this line:
if (!this._isBreaking && !this._hasBroken && this.hasCollision)
the !this._hasBroken is superfluous.
My first warning sign is this line:
brittle = entityObject.DeepCopy() as BrittleTile;
I assume DeepCopy() makes a new version of the object, and copies all it's properties, right? Seeing the code of that might help pin it down, but on that assumption...
For every Tile, you're cycling through every object in you're grid and you're completely duplicating that object as a BrittleTile, why?
My first change would be to modify that foreach to have this within it:
var brittle = entityObject as BrittleTile
if (brittle != null && hasCollision){
if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
this._isBreaking = true;
}
}
Not sure this is the primary cause of the slowdown, but it is definitely an issue. If you're cloning an object and then immediately throwing an object away, you're almost certainly doing something wrong. If you're cloning an object and you're not editing the properties of that copy at all (and using those edits), you're definitely doing something wrong. I'd be wary before using a method like that unless you're really sure that's what you want.
So I Have 2 Boolean's "FacingRight" and "FacingLeft" they aren't working as I would like and I thought of a better idea but have absolutely no idea on how to go about doing it.
I want to make FacingRight = true and FacingLeft = false if the X position value of the gameobject(player) has increased, which means it moved right, FacingRight = false and FacingLeft = true when the X value has decreased.
any help would be greatly appreciated.
Here's my current code if that helps.
public float fireAnimDelay;
Animator anim;
public bool FacingRight = false;
public bool FacingLeft = false;
// Use this for initialization
void Awake()
{
anim = GetComponent<Animator>();
anim.GetFloat("Speed");
}
// Update is called once per frame
void Update()
{
if (anim.GetFloat("Speed") >= 0.1f) // If speed is positive you are facing right
{
FacingRight = true;
Debug.Log("FacingRight");
}
if (anim.GetFloat("Speed") <= -0.1f) // if speed is negative you are facing left
{
FacingLeft = true;
}
if (anim.GetFloat("Speed") == 0.0f) // if speed is 0 you are idle
{
FacingRight = false;
FacingLeft = false;
}
if (Input.GetKey(KeyCode.Z) && FacingRight == true)
{
FacingLeft = false;
anim.SetBool("Firing", true);
anim.SetBool("FacingRight", true);
anim.SetBool("FacingLeft", false);
StartCoroutine(FireDelay());
}
if (Input.GetKey(KeyCode.Z) && FacingLeft == true)
{
FacingRight = true;
anim.SetBool("Firing", true);
anim.SetBool("FacingLeft", true);
anim.SetBool("FacingRight", false);
StartCoroutine(FireDelay());
}
}
IEnumerator FireDelay()
{
yield return new WaitForSeconds(fireAnimDelay);
anim.SetBool("Firing", false);
}
An efficient way to achieve this is to make use of one or more events. Although you can also achieve this using other techniques, event-base programming gives you priceless advantages of which the simplest one is to allow you to run different task when your value has changes in different context. (you can read more on events through Google)
The following code provides an example of how you can apply something similar in your code:
public class FloatIncreasing
{
private float _Value;
public float Value {
get {
return _Value;
}
set {
ValueChangeEvent(this, _Value >= value);
_Value = value;
}
}
public Boolean HasIncreased { get; private set; }
public event EventHandler<Boolean> ValueChangeEvent;
public FloatIncreasing() {
this.ValueChangeEvent += OnValueChanged;
}
public virtual void OnValueChanged(Object sender, Boolean value) {
HasIncreased = value;
// You can add a more appropriate default behavior in here.
}
}
Considering this code, you can consume it the following way:
class Program
{
static FloatIncreasing test = new FloatIncreasing();
static void Main(string[] args) {
test.ValueChangeEvent += Test_ValueChangeEvent;
test.Value = 0;
test.Value = 10;
test.Value = 3;
Console.ReadKey(true);
}
private static void Test_ValueChangeEvent(object sender, bool e)
{
Console.WriteLine(e ? "Value Decreased or Not Changed" : "Value increased");
}
}
Please note that anytime the test.Value is changed, the corresponding event is triggered allowing you to modify your boolean value.
You have a logic error in your code:
if (Input.GetKey(KeyCode.Z) && FacingRight == true) {
FacingLeft = false;
}
if (Input.GetKey(KeyCode.Z) && FacingLeft == true) {
FacingRight = true;
}
Notice how in the one instance you set Left to false if facing right, but in the complimentary block you set Right to true!
Also, anim.GetFloat("Speed") >= 0.1f You should check < or > than 0, otherwise values between 0 and 0.1 aren't going to be detected (or use if...elseif...else).
A better approach would be to reduce the FacingLeft/Right variable to a single variable:
enum Facing { NONE, LEFT, RIGHT }
Facing playerFacing = Facing.NONE;
//...
if (Input.GetKey(KeyCode.Z) && playerFacing == Facing.RIGHT) {
//...
}
As well as using Input.GetButton("Fire") instead of hard-coded key codes. This will allow your players to rebind the keys (maybe they don't like your WASD movement setup and prefer HJKL).
Hi,
Im working on Visual Studio Winforms and I'm trying to build tic-tac-toe.
I got stuck in the Check if player win method.
I have tried to do that in activated. little example:
private void StartForm_Activated(object sender, EventArgs e)
{
if ((_pcb1.Image == imagecircle) && (_pcb2.Image == imagecircle) && (_pcb3.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb4.Image == imagecircle) && (_pcb5.Image == imagecircle) && (_pcb6.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb7.Image == imagecircle) && (_pcb8.Image == imagecircle) && (_pcb9.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
}
(I know that there are more situations to win).
It's never get into the method, I trying to find a method that active always when the form is open. please help :)
You should check player's victory after each move of that player. I assume, that your players make their moves by clicking on "Make a Move" button or clicking on the game field. Also I assume, that you have Click event of your button or game field. So you should paste your check code in Click event of your button or game field.
Here is some code that will extend to whatever game size:
public class Level
{
private readonly Team[,] _game;
public Level(int extent)
{
_game = new Team[extent, extent];
}
public bool HasWon(Team team)
{
var yMax = GetYMax();
var xMax = GetXMax();
var won = false;
// check horizontally
for (var y = 0; y < yMax; y++)
{
won = false;
for (var x = 0; x < xMax; x++)
won |= _game[y, x] == team;
if (won) return true;
}
// TODO check vertically
// TODO check diagonally
return won;
}
public void SetTile(Team team, int x, int y)
{
var xMax = GetXMax();
var yMax = GetYMax();
if ((x < 0) || (x > xMax))
throw new ArgumentOutOfRangeException("x");
if ((y < 0) || (y > yMax))
throw new ArgumentOutOfRangeException("y");
_game[y, x] = team;
}
private int GetXMax()
{
var xMax = _game.GetUpperBound(1);
return xMax;
}
private int GetYMax()
{
var yMax = _game.GetUpperBound(0);
return yMax;
}
}
public enum Team
{
Red,
Blue
}
Things for you to do:
implement logic for checking if a team has won vertically or diagonally
implement your game using this class, drawing pictures according the array _game (make it available publicly)
study the | OR operator to understand how it's used in here : https://msdn.microsoft.com/en-us/library/6373h346.aspx
further debug the code (I haven't :)
If you want to find some method that is constantly called, so as to check whether the players have won, you can just create a Timer that runs every 1 millisecond. Then the event handler for Timer.Tick would be such a method.
However, you shouldn't find such a method to check for winning/losing. It's a waste of resources to check for that every 1 millisecond.
Think, what action can affect the result of a game of tic tac toe? It's of course when either player places something (X or O) on the board! That is when you need to check whether someone has won. Also, if the thing placed is a X, you don't need to check whether the player who is playing O has won, because that's simply impossible!
Also, checking whether the image in a picture box is equal to the X or O image is really "non abstract" code. Try to put these things into a model by abstraction.