I'm literally banging my head against a wall with this one.
I am creating a location based game in Unity and following all instructions from a book. We have used the standard 'google map tile' script and 'GPS location services' script that Unity provide in standard assets.
Now, when I enter play mode everything looks great but when deploying to my iPhone then no map is being rendered... only the rubbish red question marks!
Furthermore my phone isn't even being asked to ALLOW LOCATION and when I go to location services for the build there is no option for ENABLE.
Is this a setting that needs to be turned on in Xcode prior to build perhaps for location enabling?
public enum MapType
{
RoadMap,
Satellite,
Terrain,
Hybrid
}
private const string GOOGLE_MAPS_URL = "http://maps.googleapis.com/maps/api/staticmap";
public int zoomLevel = 1;
public MapType mapType = MapType.RoadMap;
public int size = 640;
public bool doubleResolution = true;
public GPSLocationService gpsLocationService;
public MapLocation worldCenterLocation;
public MapLocation tileCenterLocation;
public Vector2 TileOffset;
public Vector2 TopLeftCorner;
public Vector2 BottomRightCorner;
private double lastGPSUpdate;
// Use this for initialization
void Start ()
{
RefreshMapTile ();
}
// Update is called once per frame
void Update ()
{
if (gpsLocationService != null &&
gpsLocationService.IsServiceStarted &&
lastGPSUpdate < gpsLocationService.Timestamp)
{
lastGPSUpdate = gpsLocationService.Timestamp;
worldCenterLocation.Latitude = gpsLocationService.Latitude;
worldCenterLocation.Longitude = gpsLocationService.Longitude;
print("GoogleMapTile refreshing map texture");
RefreshMapTile();
}
}
public void RefreshMapTile() {
StartCoroutine(_RefreshMapTile());
}
IEnumerator _RefreshMapTile ()
{
tileCenterLocation.Latitude = GoogleMapUtils.adjustLatByPixels(worldCenterLocation.Latitude, (int)(size * 1 * TileOffset.y), zoomLevel);
tileCenterLocation.Longitude = GoogleMapUtils.adjustLonByPixels(worldCenterLocation.Longitude, (int)(size * 1 * TileOffset.x), zoomLevel);
var url = GOOGLE_MAPS_URL;
var queryString = "";
queryString += "center=" + WWW.UnEscapeURL (string.Format ("{0},{1}", tileCenterLocation.Latitude, tileCenterLocation.Longitude));
queryString += "&zoom=" + zoomLevel.ToString ();
queryString += "&size=" + WWW.UnEscapeURL (string.Format ("{0}x{0}", size));
queryString += "&scale=" + (doubleResolution ? "2" : "1");
queryString += "&maptype=" + mapType.ToString ().ToLower ();
queryString += "&format=" + "png";
//styles
queryString += "&style=element:geometry|invert_lightness:true|weight:3.1|hue:0x00ffd5";
queryString += "&style=element:labels|visibility:off";
var usingSensor = false;
if MOBILE_INPUT
usingSensor = Input.location.isEnabledByUser && Input.location.status == LocationServiceStatus.Running;
endif
queryString += "&sensor=" + (usingSensor ? "true" : "false");
//set map bounds rect
TopLeftCorner.x = GoogleMapUtils.adjustLonByPixels(tileCenterLocation.Longitude, -size, zoomLevel);
TopLeftCorner.y = GoogleMapUtils.adjustLatByPixels(tileCenterLocation.Latitude, size, zoomLevel);
BottomRightCorner.x = GoogleMapUtils.adjustLonByPixels(tileCenterLocation.Longitude, size, zoomLevel);
BottomRightCorner.y = GoogleMapUtils.adjustLatByPixels(tileCenterLocation.Latitude, -size, zoomLevel);
print(string.Format("Tile {0}x{1} requested with {2}", TileOffset.x, TileOffset.y, queryString));
var req = new WWW(url + "?" + queryString);
//var req = new WWW("https://maps.googleapis.com/maps/api/staticmap?center=50.917316,-114.080923&zoom=17&format=png&sensor=false&size=640x640&scale=2&maptype=roadmap&style=feature:landscape.man_made|visibility:on|invert_lightness:true");
yield return req;
GetComponent<Renderer>().material.mainTexture = req.texture;
print(string.Format("Tile {0}x{1} textured", TileOffset.x, TileOffset.y));
}
}
}
Many thanks for your help
Carl
So I'm playing around with the BouncyGame. I made it so that when you start the game you need to press the screen for it to start. I would like to implement this whenever you play a new round as well. I tried to reuse this att the bottom of my code but it made it extremely laggy.
// Register for touch events
var touchListener = new CCEventListenerTouchAllAtOnce();
touchListener.OnTouchesEnded = OnTouchesEnded;
touchListener.OnTouchesMoved = OnTouchesEnded;
AddEventListener(touchListener, this);
}
void OnTouchesEnded(List<CCTouch> touches, CCEvent touchEvent)
{
if (touches.Count > 0)
{
Schedule(RunGameLogic);
scoreLabel.Text = "Score: 0";
paddleSprite.RunAction(new CCMoveTo(.1f, new CCPoint(touches[0].Location.X, paddleSprite.PositionY)));
}
}
I have no idea how to do this, tried for 2 hours with 0 results. Any suggestions are welcome.
Here's the full code.
using System;
using System.Collections.Generic;
using CocosSharp;
using Microsoft.Xna.Framework;
namespace CocosSharpGameTest
{
public class IntroLayer : CCLayerColor
{
// Define a label variable
CCLabel scoreLabel;
CCSprite paddleSprite, ballSprite;
public IntroLayer() : base(CCColor4B.Black)
{
// create and initialize a Label
scoreLabel = new CCLabel("Tap to GO!", "Arial", 80, CCLabelFormat.SystemFont);
// add the label as a child to this Layer
scoreLabel.PositionX = 50;
scoreLabel.PositionY = 1000;
scoreLabel.AnchorPoint = CCPoint.AnchorUpperLeft;
AddChild(scoreLabel);
paddleSprite = new CCSprite("paddle.png");
AddChild(paddleSprite);
ballSprite = new CCSprite("ball.png");
AddChild(ballSprite);
}
protected override void AddedToScene()
{
base.AddedToScene();
// Use the bounds to layout the positioning of our drawable assets
CCRect bounds = VisibleBoundsWorldspace;
// position the label on the center of the screen
paddleSprite.PositionX = 100;
paddleSprite.PositionY = 100;
ballSprite.PositionX = 320;
ballSprite.PositionY = 640;
// Register for touch events
var touchListener = new CCEventListenerTouchAllAtOnce();
touchListener.OnTouchesEnded = OnTouchesEnded;
touchListener.OnTouchesMoved = OnTouchesEnded;
AddEventListener(touchListener, this);
}
void OnTouchesEnded(List<CCTouch> touches, CCEvent touchEvent)
{
if (touches.Count > 0)
{
Schedule(RunGameLogic);
scoreLabel.Text = "Score: 0";
paddleSprite.RunAction(new CCMoveTo(.1f, new CCPoint(touches[0].Location.X, paddleSprite.PositionY)));
}
}
float ballXVelocity;
float ballYVelocity;
// How much to modify the ball's y velocity per second:
const float gravity = 140;
int score = 0;
void RunGameLogic(float frameTimeInSeconds)
{
// This is a linear approximation, so not 100% accurate
ballYVelocity += frameTimeInSeconds * -gravity;
ballSprite.PositionX += ballXVelocity * frameTimeInSeconds;
ballSprite.PositionY += ballYVelocity * frameTimeInSeconds;
bool overlap = ballSprite.BoundingBoxTransformedToParent.IntersectsRect(paddleSprite.BoundingBoxTransformedToParent);
bool movingDown = ballYVelocity < 0;
if (overlap && movingDown)
{
ballYVelocity *= -1;
const float minXVelocity = -300;
const float maxXVelocity = 300;
ballXVelocity = CCRandom.GetRandomFloat(minXVelocity, maxXVelocity);
score++;
scoreLabel.Text = "Score: " + score;
}
float ballRight = ballSprite.BoundingBoxTransformedToParent.MaxX;
float ballLeft = ballSprite.BoundingBoxTransformedToParent.MinX;
float screenRight = VisibleBoundsWorldspace.MaxX;
float screenLeft = VisibleBoundsWorldspace.MinX;
bool shouldReflectXVelocity =
(ballRight > screenRight && ballXVelocity > 0) ||
(ballLeft < screenLeft && ballXVelocity < 0);
if (shouldReflectXVelocity)
{
ballXVelocity *= -1;
}
if (ballSprite.PositionY < VisibleBoundsWorldspace.MinY)
{
ballSprite.PositionX = 320;
ballSprite.PositionY = 640;
ballXVelocity = 0;
ballYVelocity = 0;
ballYVelocity *= -1;
scoreLabel.Text = "Score: 0";
score = 0;
}
}
}
}
Thanks in advance!
Figured it out!
There is an "Unschedule" Method built into Cocossharp.
Ref. https://developer.xamarin.com/api/namespace/CocosSharp/
I just added
Unschedule(RunGameLogic);
at the very en of my RunGameLogic method under
if (ballSprite.PositionY < VisibleBoundsWorldspace.MinY)
So once the ballSprite is out of bounds it will Unschedule what i Scheduled in my OntouchesEnded method. That means the code goes back to listening for touches.
Might have made some errors, but this is as best I could figure it out and it works!
At the top of the script i added the variable _birdscount:
public int _birdscount;
Then in a LoadSettings function i added the line:
res.boidSettings [0].BirdsCount = _birdscount;
So each time i change the value of _birdscount in the editor in the Inspector and then running the game it will take effect.
Settings LoadSettings()
{
TextAsset temp = (TextAsset)Resources.Load(SettingsFileName);
var str = new StringReader(temp.text);
Resources.UnloadAsset(temp);
res = (Settings)serializer.Deserialize(str);
while( res.boidSettings.Count < instancePoints.Length )
res.boidSettings.Add(new BoidSettingsEx());
res.boidSettings [0].BirdsCount = _birdscount;
return res;
}
But now i want to make that also when the game is running if i change the value of the _birdscount in the Inspector it will take effect.
So i tried in the Update function to do that if you click/press the button e it will make the changes while the game is running but it's not changing the birds count in real time. So i'm guessing just calling:
LoadSettings ();
Restart ();
Is not enough or not right.
void Update()
{
if (Input.GetKeyDown ("space"))
OnSettingsClick ();
if (Input.GetKeyDown ("e"))
{
LoadSettings ();
Restart ();
}
//We call it here to be sure that click on button desn't lead to camera target changing
if( !guiTools.MouseOverGUI && Input.GetMouseButtonDown(0) )
cameraControl.CheckForNewTarget( Input.mousePosition );
guiTools.ManualUpdate();
}
This is the complete script if it's needed:
using UnityEngine;
using System.Xml.Serialization;
using System.IO;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
public CameraControl cameraControl;
public Object birdPrefab;
public Transform birdParent;
private Transform cameraObj;
public Transform[] instancePoints;
public int _birdscount;
private Settings res;
[System.Serializable]
public class BoidSettingsEx: Boid.Settings
{
public float BirdsCount = 100;
}
[System.Serializable]
public struct Size
{
public int width;
public int height;
public Size( int width, int height )
{
this.width = width;
this.height = height;
}
public bool IsValid { get{ return width > 0 && height > 0; } }
}
[System.Serializable]
public class Settings
{
public List<BoidSettingsEx> boidSettings = new List<BoidSettingsEx>();
public int instancePointNum = 0;
public Boid.DebugSettings debugSettings = new Boid.DebugSettings();
[System.Xml.Serialization.XmlIgnore]
public bool showSettingsWindow = false;
[System.Xml.Serialization.XmlIgnore]
public int settingsWindowTab = 0;
[System.Xml.Serialization.XmlIgnore]
public Size screenSize = new Size();
}
[SerializeField]
private Settings settings = new Settings();
//static is used to keep values after restart
static private Settings globalSettings;
void Start()
{
if( globalSettings == null )
{
settings = LoadSettings();
globalSettings = settings;
}
else
settings = globalSettings;
InstantiateBirds();
cameraControl.Enabled = !settings.showSettingsWindow;
}
void InstantiateBirds()
{
var ip = instancePoints[settings.instancePointNum];
var sts = settings.boidSettings[settings.instancePointNum];
sts.Trace = ip.GetComponent<Trace>();
const float size = 0.1f;
cameraObj = InstantiateBird( ip.position, ip.rotation, sts ).transform;
cameraControl.Target = cameraObj;
MathTools.FillSquareUniform( sts.BirdsCount, delegate ( int x, int y )
{
if( x != 0 || y != 0 )
InstantiateBird(
cameraObj.position + new Vector3( size * x, size * y, Random.Range(-size, size) ),
MathTools.RandomYawPitchRotation(),
sts
);
});
}
private readonly XmlSerializer serializer = new XmlSerializer(typeof(Settings));
private string SettingsFileName { get{ return "Settings"; } }
private string SettingsFilePath { get{ return Application.dataPath + Path.DirectorySeparatorChar + "Resources" + Path.DirectorySeparatorChar + SettingsFileName + ".xml";} }
Settings LoadSettings()
{
TextAsset temp = (TextAsset)Resources.Load(SettingsFileName);
var str = new StringReader(temp.text);
Resources.UnloadAsset(temp);
res = (Settings)serializer.Deserialize(str);
while( res.boidSettings.Count < instancePoints.Length )
res.boidSettings.Add(new BoidSettingsEx());
res.boidSettings [0].BirdsCount = _birdscount;
return res;
}
void SaveSettings()
{
if (Application.isEditor) {
using (var str = new FileStream (SettingsFilePath, FileMode.Create))
serializer.Serialize (str, settings);
}
}
private GameObject InstantiateBird( Vector3 position, Quaternion rotation, Boid.Settings boidSettings )
{
var obj = (GameObject)Instantiate( birdPrefab, position, rotation );
var boid = obj.GetComponent<Boid>();
obj.transform.parent = birdParent;
boid.SettingsRef = boidSettings;
boid.DebugSettingsRef = settings.debugSettings;
return obj;
}
public static Boid.Settings GetSettings( GameObject obj )
{
var main = Camera.main.GetComponent<Main>();
return main.settings.boidSettings[main.settings.instancePointNum];
}
private GuiTools guiTools = new GuiTools();
void GuiBoidSettings()
{
var sts = settings.boidSettings[settings.instancePointNum];
GUILayout.BeginHorizontal();
GUILayout.BeginVertical();
var newInstancePointNum = guiTools.Switcher( settings.instancePointNum, "Instance point", new string[]{ "WayPoints", "Box", "Freedom" } );
guiTools.FloatParam( ref sts.SpeedMultipliyer, "Speed", 20 );
guiTools.FloatParam( ref sts.ViewRadius, "Bird's view distance", 20 );
guiTools.FloatParam( ref sts.OptDistance, "Optimal distance between birds", 2 );
guiTools.FloatParam( ref sts.AligmentForcePart, "Fraction of flock aligment force", 0.01f );
GUILayout.EndVertical();
GUILayout.BeginVertical();
guiTools.FloatParam( ref sts.BirdsCount, "Number of birds (Restart Required)", 1000);
guiTools.FloatParam( ref sts.TotalForceMultipliyer, "Reaction speed", 50 );
guiTools.FloatParam( ref sts.Inertness, "Inertness", 1 );
guiTools.FloatParam( ref sts.VerticalPriority, "Flock's shape deformation", 3 );
guiTools.FloatParam( ref sts.AttractrionForce, "Waypoint's attraction force", 1.0f );
GUILayout.EndVertical();
GUILayout.EndHorizontal();
if( GUILayout.Button("Load default parameters") )
{
var defSt = LoadSettings();
settings.boidSettings[settings.instancePointNum] = defSt.boidSettings[settings.instancePointNum];
Restart();
}
if( newInstancePointNum != settings.instancePointNum )
{
settings.instancePointNum = newInstancePointNum;
cameraControl.ResetStoredSettings();
Restart();
}
}
void GuiDebugDrawSettings()
{
GUILayout.BeginVertical("box");
var newFullScreen = GUILayout.Toggle( Screen.fullScreen, "Fullscreen" );
GUILayout.EndVertical();
if( newFullScreen != Screen.fullScreen )
if( newFullScreen)
{
settings.screenSize = new Size( Screen.width, Screen.height );
Screen.SetResolution( Screen.currentResolution.width, Screen.currentResolution.height, true );
}
else if( settings.screenSize.IsValid )
Screen.SetResolution( settings.screenSize.width, settings.screenSize.height, false );
else
Screen.fullScreen = false;
GUILayout.BeginVertical("box");
guiTools.Toggle( ref settings.debugSettings.enableDrawing, "Algorithm Explanation Vectors" );
GUILayout.EndVertical();
if( settings.debugSettings.enableDrawing )
{
GUILayout.BeginVertical("box");
guiTools.Toggle( ref settings.debugSettings.velocityDraw, "Resulting velocity" );
guiTools.Toggle( ref settings.debugSettings.cohesionForceDraw, "Cohesion force" );
guiTools.Toggle( ref settings.debugSettings.collisionsAvoidanceForceDraw, "Collision Avoidance force" );
guiTools.Toggle( ref settings.debugSettings.positionForceDraw, "Cohesion + Collision Avoidance forces" );
guiTools.Toggle( ref settings.debugSettings.obstaclesAvoidanceDraw, "Obstacles Avoidance forces" );
guiTools.Toggle( ref settings.debugSettings.alignmentForceDraw, "Aligment force" );
guiTools.Toggle( ref settings.debugSettings.attractionForceDraw, "Attraction force" );
guiTools.Toggle( ref settings.debugSettings.totalForceDraw, "Resulting force" );
GUILayout.EndVertical();
}
}
void GuiInfo()
{
var text =
"<b><color=yellow>Bird Flocking Simulation</color></b>\n" +
" \n" +
" <b><color=orange>Dmitry Shesterkin 2013</color></b>\n" +
" http://black-square.github.io/BirdFlock/\n" +
" dfb#yandex.ru\n" +
" \n" +
"<b><color=yellow>Controls</color></b>\n" +
" \n" +
" <b><color=orange>Space</color></b> - Toggle settings\n" +
" <b><color=orange>Mouse</color></b> - Camera rotation\n" +
" <b><color=orange>Left Mouse Button Click</color></b> - Attach camera to target\n" +
" <b><color=orange>Tab</color></b> - Detach camera from target\n" +
" <b><color=orange>T</color></b> - Rotate camera with target\n" +
" <b><color=orange>Mouse ScrollWheel / Up / Down</color></b> - Zoom\n" +
" <b><color=orange>W/A/S/D/Q/E</color></b> - Manual camera movement\n" +
" <b><color=orange>Hold Right Mouse Button</color></b> - Disable camera rotation";
GUI.skin.box.richText = true;
GUI.skin.box.wordWrap = false;
GUI.skin.box.alignment = TextAnchor.MiddleLeft;
GUILayout.Box( text );
}
void SettingsWindow( int windowId )
{
GUILayout.BeginVertical();
settings.settingsWindowTab = GUILayout.Toolbar( settings.settingsWindowTab, new string[]{ "Birds Params", "Screen", "Info" } );
switch(settings.settingsWindowTab)
{
case 0:
GuiBoidSettings();
break;
case 1:
GuiDebugDrawSettings();
break;
case 2:
GuiInfo();
break;
}
GUILayout.EndVertical();
}
delegate void SimpleDlg();
void OnSettingsClick()
{
settings.showSettingsWindow = !settings.showSettingsWindow;
if (!settings.showSettingsWindow)
SaveSettings ();
cameraControl.Enabled = !settings.showSettingsWindow;
}
void Restart()
{
guiTools.ClearCache();
//Application.LoadLevel (Application.loadedLevelName);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
void Update()
{
if (Input.GetKeyDown ("space"))
OnSettingsClick ();
if (Input.GetKeyDown ("e"))
{
LoadSettings ();
Restart ();
}
//We call it here to be sure that click on button desn't lead to camera target changing
if( !guiTools.MouseOverGUI && Input.GetMouseButtonDown(0) )
cameraControl.CheckForNewTarget( Input.mousePosition );
guiTools.ManualUpdate();
}
void OnGUI()
{
var tlbLabels = new string[] { "Restart", "Settings" };
var tlbActions = new SimpleDlg[] { Restart, OnSettingsClick };
var tlbResult = GUILayout.Toolbar( -1, tlbLabels );
guiTools.CheckMouseOverForLastControl();
if( tlbResult >= 0 )
tlbActions[tlbResult]();
if( settings.showSettingsWindow )
GUILayout.Window(0, new Rect(10, 30, 2, 2), SettingsWindow, "Settings");
}
}
I made a simulation in OpenSimulator. I changed the terrain to resemble that of Atlantis and used the OpenSimTide module to have the tide cause the disappearance of Atlantis.
Now the OpenSimTide module works, but for some reason I just can't find out how I make the terrain go lower whenever the tide reaches a specific level. How can I achieve this?
Here's what i have up until now:
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
using Mono.Addins;
[assembly: Addin("OpenSimTide", "0.2")]
[assembly: AddinDependency("OpenSim.Region.Framework",
OpenSim.VersionInfo.VersionNumber)]
namespace TideModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OpenSimTide")]
public class OpenSimTide : INonSharedRegionModule
{
#region Fields
private static readonly ILog m_log = LogManager.GetLogger (MethodBase.GetCurrentMethod ().DeclaringType);
public string Name { get { return m_name; } }
public Type ReplaceableInterface { get { return null; } }
private const int TICKS_PER_SECOND = 10000000;
public string m_name = "OpenSimTide";
private string m_regionConfigDir = "";
private uint m_frame = 0;
private int m_frameUpdateRate = 100;
private bool m_enabled = false;
private bool m_ready = false;
private float m_tideLevel = 20.0f; //current water level in m
private float m_lowTide = 18.0f; //low water level in m
private float m_highTide = 22.0f; //high water level in m
private ulong m_cycleTime = 3600; //low->high->low time in seconds
private DateTime m_lowTideTime = new DateTime(); // datetime indicating when next low tide will be
private DateTime m_highTideTime = new DateTime(); // datetime indicating when next hightide will be
private bool m_tideDirection = true; // which direction is the tide travelling, 'Coming In'(true) or 'Going Out'(false)
private bool m_lastTideDirection = true;
private bool m_tideInfoDebug = false; //do we chat the tide to the OpenSim console?
private bool m_tideInfoBroadcast = true; //do we chat the tide to the region?
private int m_tideInfoChannel = 5555; //chat channel for all tide info
private int m_tideLevelChannel = 5556; //chat channel for just the tide level in m
private int m_tideAnnounceCount = 5; //how many times do we announce the turning tide
private int m_tideAnnounceCounter = 0; //counter we use to count announcements of low or high tide
private string m_tideAnnounceMsg = "";
private ITerrainChannel m_channel;
public scene m_scene;
public IConfigSource m_config;
public RegionInfo m_regionInfo;
public Dictionary<string, Scene> mScene = new Dictionary<string, Scene> ();
public Vector3 m_shoutPos = new Vector3(128f, 128f, 30f);
#endregion
#region IRegionModuleBase implementation
public void Initialise (IConfigSource source)
{
m_config = source;
}
public void Close ()
{
if (m_enabled) {
m_scene.EventManager.OnFrame -= TideUpdate;
}
}
public void AddRegion (Scene scene)
{
IConfig cnf;
m_log.InfoFormat("[{0}]: Adding region '{1}' to this module", m_name, scene.RegionInfo.RegionName);
cnf = m_config.Configs["Startup"];
m_regionConfigDir = cnf.GetString("regionload_regionsdir", Path.Combine(Util.configDir(), "bin/Regions/"));
cnf = m_config.Configs[scene.RegionInfo.RegionName];
if(cnf == null)
{
m_log.InfoFormat("[{0}]: No region section [{1}] found in addon-modules/{2}/config/*.ini configuration files.", m_name, scene.RegionInfo.RegionName, m_name);
//string moduleConfigFile = Path.Combine(Util.configDir(),m_name + ".ini");
string moduleConfigFile = Path.Combine(m_regionConfigDir, "Regions.ini");
try
{
m_log.InfoFormat("[{0}]: Checking {1} for [{2}] section containing valid config keys", m_name, moduleConfigFile, scene.RegionInfo.RegionName);
m_config = new IniConfigSource(moduleConfigFile);
cnf = m_config.Configs[scene.RegionInfo.RegionName];
}
catch (Exception)
{
cnf = null;
}
if (cnf == null)
{
m_log.InfoFormat("[{0}]: No region section [{1}] found in configuration {2}. Tide in this region is set to Disabled", m_name, scene.RegionInfo.RegionName, moduleConfigFile);
m_enabled = false;
return;
}
}
m_enabled = cnf.GetBoolean("TideEnabled", false);
if (m_enabled)
{
m_frameUpdateRate = cnf.GetInt("TideUpdateRate", 150);
m_lowTide = cnf.GetFloat("TideLowWater", 18.0f);
m_highTide = cnf.GetFloat("TideHighWater", 22.0f);
m_cycleTime = (ulong)cnf.GetInt("TideCycleTime", 3600);
m_tideInfoDebug = cnf.GetBoolean("TideInfoDebug", false);
m_tideInfoBroadcast = cnf.GetBoolean("TideInfoBroadcast", true);
m_tideInfoChannel = cnf.GetInt("TideInfoChannel", 5555);
m_tideLevelChannel = cnf.GetInt("TideLevelChannel", 5556);
m_tideAnnounceCount = cnf.GetInt("TideAnnounceCount", 5);
m_log.InfoFormat("[{0}]: Enabled with an update rate every {1} frames, Low Water={2}m, High Water={3}m, Cycle Time={4} secs", m_name, m_frameUpdateRate, m_lowTide, m_highTide, m_cycleTime);
m_log.InfoFormat("[{0}]: Info Channel={1}, Water Level Channel={2}, Info Broadcast is {3}, Announce Count={4}", m_name, m_tideInfoChannel, m_tideLevelChannel, m_tideInfoBroadcast, m_tideAnnounceCounter);
m_frame = 0;
m_ready = true; // Mark Module Ready for duty
m_shoutPos = new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 30f);
scene.EventManager.OnFrame += TideUpdate;
m_scene = scene;
}
else
{
m_log.InfoFormat("[{0}]: Tide in this region is set to Disabled", m_name);
}
}
public void RemoveRegion (Scene scene)
{
m_log.InfoFormat("[{0}]: Removing region '{1}' from this module", m_name, scene.RegionInfo.RegionName);
if (m_enabled)
{
scene.EventManager.OnFrame -= TideUpdate;
}
}
public void RegionLoaded (Scene scene)
{
}
#endregion
#region TideModule
// Place your methods here
public void TideUpdate ()
{
ulong timeStamp;
double cyclePos; //cycles from 0.0000000001 to 0.999999999999
double cycleRadians;
double tideRange;
double tideMiddle;
string tideLevelMsg;
if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready) {
return;
}
timeStamp = (ulong) (DateTime.Now.Ticks);
cyclePos = (double)(timeStamp % (m_cycleTime * TICKS_PER_SECOND)) / (m_cycleTime * TICKS_PER_SECOND);
cycleRadians = cyclePos * Math.PI * 2;
if (cyclePos < 0.5) m_tideDirection = false; else m_tideDirection = true;
if (m_tideDirection != m_lastTideDirection)
{ //if the tide changes re-calculate the tide times
if (cyclePos < 0.5)
{ // tide just changed to be high->low
m_lowTideTime = DateTime.Now.AddSeconds((double)(m_cycleTime * (0.5 - cyclePos)));
m_highTideTime = m_lowTideTime.AddSeconds((double)(m_cycleTime / 2));
m_tideAnnounceMsg = "High Tide";
}
else
{ //tide just changed to be low->high
m_highTideTime = DateTime.Now.AddSeconds((double)(m_cycleTime * (1.0 - cyclePos)));
m_lowTideTime = m_highTideTime.AddSeconds((double)(m_cycleTime / 2));
m_tideAnnounceMsg = "Low Tide";
}
m_lastTideDirection = m_tideDirection;
}
tideRange = (double) (m_highTide - m_lowTide) / 2;
tideMiddle = (double) m_lowTide + tideRange;
m_tideLevel = (float) (Math.Cos(cycleRadians) * tideRange + tideMiddle);
tideLevelMsg = "Current Server Time: " + DateTime.Now.ToString("T") + "\n";
tideLevelMsg += "Current Tide Level: " + m_tideLevel.ToString() + "\n";
tideLevelMsg += "Low Tide Time: " + m_lowTideTime.ToString("T") + "\n";
tideLevelMsg += "Low Tide Level: " + m_lowTide.ToString() + "\n";
tideLevelMsg += "High Tide Time: " + m_highTideTime.ToString("T") + "\n";
tideLevelMsg += "High Tide Level: " + m_highTide.ToString() + "\n";
tideLevelMsg += "Tide Direction: " + ((m_tideDirection) ? "Coming In" : "Going Out") + "\n";
tideLevelMsg += "Cycle Position: " + cyclePos.ToString() + "\n";
if (m_tideAnnounceMsg != "")
{
if (m_tideAnnounceCounter++ > m_tideAnnounceCount)
{
m_tideAnnounceCounter = 0;
m_tideAnnounceMsg = "";
}
else
{
tideLevelMsg += "Tide Warning: " + m_tideAnnounceMsg + "\n";
}
}
if (m_tideInfoDebug) m_log.InfoFormat("[{0}]: Sea Level currently at {1}m in Region: {2}", m_name, m_tideLevel, m_scene.RegionInfo.RegionName);
if (m_tideInfoBroadcast && m_tideDirection)
{
m_scene.SimChatBroadcast(Utils.StringToBytes(tideLevelMsg), ChatTypeEnum.Region, m_tideInfoChannel, m_shoutPos, "TIDE", UUID.Zero, false);
m_scene.SimChatBroadcast(Utils.StringToBytes(m_tideLevel.ToString()), ChatTypeEnum.Region, m_tideLevelChannel, m_shoutPos, "TIDE", UUID.Zero, false);
}
if (m_tideInfoDebug) m_log.InfoFormat("[{0}]: Updating Region: {1}", m_name, m_scene.RegionInfo.RegionName);
m_scene.RegionInfo.RegionSettings.WaterHeight = m_tideLevel;
m_scene.EventManager.TriggerRequestChangeWaterHeight(m_tideLevel);
m_scene.EventManager.TriggerTerrainTick();
if (m_tideInfoBroadcast && !m_tideDirection)
{
m_scene.SimChatBroadcast(Utils.StringToBytes(tideLevelMsg), ChatTypeEnum.Region, m_tideInfoChannel, m_shoutPos, "TIDE", UUID.Zero, false);
m_scene.SimChatBroadcast(Utils.StringToBytes(m_tideLevel.ToString()), ChatTypeEnum.Region, m_tideLevelChannel, m_shoutPos, "TIDE", UUID.Zero, false);
}
}
private void InterfaceMultiplyTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] *= (double)args[0];
}
public void UpdateTerrainWithTide()
{
float terrain_scale = 0.75 * m_channel.Height;
float terrain_scale2 = 0.95 * m_channel.Height;
while (tideDirection == true)
{
if (m_tideLevel > terrain_scale && m_tideLevel < terrain_scale2)
{
InterfaceMultiplyTerrain(0.95);
}
}
}
#endregion
}
}
I am trying to make an A* pathfinder for my game in C# XNA 4.0.
If the pathfinder executes once, then the monster moves correctly. But while the monster is moving the pathfinder executes again, and uses the current position of the enemy.
The pathfider takes about a half to one second to finish. So when the pathfinder is done and returns the new path, the monster have moved away from the position used meanwhile. So now the monster moves the whole way back to the position used, just to start the new path.
How do i solve this problem?
I dont know what you need. If it's the pathfinder code you'll need to see then i'll post it but here is the zombie class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;
namespace *Private name*
{
class Zombie : Obj
{
ContentManager Content;
private Vector2 dest;
private bool[,] map;
private List<Note> path = new List<Note>();
private int PathIndex = 0;
private bool queued = false;
private int queTimer = 0;
private int queTime = 10;
private bool finding = false;
private bool walkable = false;
private Thread t;
public Zombie(Vector2 pos, string sprName, int MaxHP, int HP, int damage) : base(pos, sprName, MaxHP, HP)
{
position = pos;
spriteName = sprName;
maxHealth = MaxHP;
if (HP > maxHealth)
Health = maxHealth;
else if (HP < 0)
Health = 1;
else
Health = HP;
maxHealth = 10;
Health = 10;
solid = true;
speed = 1.0f;
dest = position;
this.damage = damage;
}
//Loads the content and sets some values
public override void LoadContent(ContentManager content)
{
spriteTexture = content.Load<Texture2D>(spriteName);
spriteRectangle = new Rectangle((int)position.X, (int)position.Y, spriteTexture.Width, spriteTexture.Height);
centerPosRec.X = (int)position.X + (spriteRectangle.Height / 2);
centerPosRec.Y = (int)position.Y + (spriteRectangle.Width / 2);
Content = content;
}
public override void Update()
{
if (!alive) return;
if (Health <= 0)
alive = false;
if (attackCoolDown > 0)
attackCoolDown--;
if (queTimer > queTime)
{
queTimer = 0;
NewSetPath();
}
else
{ queTimer++; }
MoveToDestination();
spriteRectangle.X = (int)position.X;
spriteRectangle.Y = (int)position.Y;
centerPosRec.X = (int)position.X + (spriteRectangle.Height / 2);
centerPosRec.Y = (int)position.Y + (spriteRectangle.Width / 2);
}
//Here the program finds the path
private void NewSetPath()
{
if (t != null)
if (t.IsAlive == true)
return;
dest = Player.player1.centerPosRec;
if (!finding)
{
finding = true;
t = new Thread(NewFindPath);
t.Start();
}
if (!t.IsAlive && finding)
{
t.Abort();
finding = false;
queued = false;
PathIndex = 0;
}
}
//Here it also finds the path
private void NewFindPath()
{
map = MyPathFinder.writeMap();
MyPathFinder finder;
finder = new MyPathFinder(map);
path = finder.findPath(this.centerPosRec, this.dest);
}
//Moves to the next point/note in the path list
private void MoveToDestination()
{
if (path == null)
{
return;
}
if (PathIndex < path.Count)
{
if (stepToPoint(path[PathIndex]))
{
PathIndex++;
}
else
{
PushTo(speed, rotation);
}
}
else if (path.Count >= 0)
{
path = null;
PathIndex = 0;
queued = false;
dest = Player.player1.position;
NewSetPath();
}
}
//Checkes for collition and distance to the point
private bool stepToPoint(Note note)
{
if (PointDist(centerPosRec.X, centerPosRec.Y, note.posRectangle.Y + (pathFinder.gridSize / 2), note.posRectangle.X + (pathFinder.gridSize / 2)) < pathFinder.gridSize / 2)
{
speed = 0;
return true;
}
rotation = Point_Direction(centerPosRec.X, centerPosRec.Y, note.posRectangle.Y + (pathFinder.gridSize / 2), note.posRectangle.X + (pathFinder.gridSize / 2));
speed = 2f;
return false;
}
public override void Draw(SpriteBatch spriteBatch)
{
try
{
Vector2 center = new Vector2(spriteTexture.Width / 2, spriteTexture.Height / 2);
foreach (Note n in path)
{
spriteBatch.Draw(Content.Load<Texture2D>("OfficeWall"), new Vector2(n.position.Y * 32, n.position.X * 32), null, Color.White, 0, center, scale, SpriteEffects.None, 0);
}
}
catch
{ }
base.Draw(spriteBatch);
try
{
spriteBatch.DrawString(Content.Load<SpriteFont>("HUDFont"), PathIndex + "/" + path.Count, new Vector2(500, 500), Color.White);
}
catch
{ }
}
//Gets distance between points
public static float PointDist(float x1, float y1, float x2, float y2)
{
float xRect = (x1 -x2) * (x1 - x2);
float yRect = (y1 - y2) * (y1 - y2);
double hRect = xRect + yRect;
float dist = (float)Math.Sqrt(hRect);
return dist;
}
//Movement
public override void PushTo(float pix, float dir)
{
float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
newX *= pix;
newY *= pix;
if (!Collision(new Vector2(newX, newY)))
{
base.PushTo(pix, dir);
}
else if (!Collision(new Vector2(0, newY)))
{
this.position += new Vector2(0, newY);
}
else if (!Collision(new Vector2(newX, 0)))
{
this.position += new Vector2(newX, 0);
}
}
public override bool Collision(Vector2 pos)
{
Rectangle area = new Rectangle(spriteRectangle.X, spriteRectangle.Y, spriteRectangle.Width, spriteRectangle.Height);
area.X += (int)pos.X;
area.Y += (int)pos.Y;
foreach (Obj o in Items.objList)
{
if (o.solid && o.alive && o != this && o.GetType() != typeof(Zombie))
{
if (area.Intersects(Player.player1.spriteRectangle))
{
if (Player.player1.alive == true && attackCoolDown == 0)
{
this.attackCoolDown = 55;
Player.player1.Health -= damage;
Player.player1.regenAfterDamageTimer = 0;
Player.player1.PushTo(5f, rotation);
return true;
}
}
if (o.spriteRectangle.Intersects(area))
{
return true;
}
}
}
return false;
}
}
}
Ok, Here's the pathfinder, it is not completely done, and I know I have to move the if statement that checks if the end position is being checked. I made it faster by making it update each tick and it is working better now. Now it takes one milisecond But here it is :D
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;
namespace *Private name*
{
class MyPathFinder
{
List<Note> path = new List<Note>();
List<Note> openList = new List<Note>();
List<Note> closedList = new List<Note>();
Note start;
Note endPos;
private Note[,] map;
public static int GridSize = 32;
bool NorthRight = false, NorthLeft = false, SouthRight = false, SouthLeft = false, EastRight = false, EastLeft = false, WestRight = false, WestLeft = false;
//string values = "";
public MyPathFinder(bool[,] cMap)
{
map = new Note[cMap.GetLength(0), cMap.GetLength(1)];
for (int x = 0; x < cMap.GetLength(0); x++)
{
for (int y = 0; y < cMap.GetLength(1); y++)
{
Rectangle rec = new Rectangle();
rec.Width = rec.Height = pathFinder.gridSize;
rec.X = x * pathFinder.gridSize;
rec.Y = y * pathFinder.gridSize;
map[x, y] = new Note();
map[x, y].walkable = cMap[x, y];
map[x, y].posRectangle = rec;
map[x, y].position = new Point(x, y);
}
}
}
public static bool[,] writeMap(params Obj[] objEx)
{
bool[,] cMap = new bool[Convert.ToInt16(Game1.room.Width / pathFinder.gridSize), Convert.ToInt16(Game1.room.Height / pathFinder.gridSize)];
//string output2 = "";
//loop through rows
for (int x = 0; x < cMap.GetLength(0); x++)
{
for (int y = 0; y < cMap.GetLength(1); y++)
{
Rectangle rec = new Rectangle();
rec.Width = rec.Height = pathFinder.gridSize;
rec.X = y * pathFinder.gridSize;
rec.Y = x * pathFinder.gridSize;
//output2 += Convert.ToString("{" + y + "," + x);
//If collision with grid then grid is unwalkable
foreach (Obj o in Items.objList)
{
if (o.spriteRectangle.Intersects(rec) && o.alive && o.solid && !objEx.Contains<Obj>(o) && o.GetType() != typeof(Zombie) && o.GetType() != typeof(Player))
{
cMap[x, y] = false;
break;
}
else
{
cMap[x, y] = true;
}
}
//output2 += " = " + cMap[x, y] + "} -- ";
}
//output2 += "\r\n";
}
//File.WriteAllText("DEBUG-Walkable.txt", output2);
return cMap;
}
public List<Note> findPath(Vector2 pos, Vector2 dest)
{
string wtf = "";
int num = 0;
path.Clear();
openList.Clear();
closedList.Clear();
Point startPos = new Point(Convert.ToInt16(Math.Floor((double)(pos.Y / GridSize))), Convert.ToInt16(Math.Floor((double)(pos.X / GridSize))));
Point end = new Point(Convert.ToInt16(Math.Floor((double)(dest.Y / GridSize))), Convert.ToInt16(Math.Floor((double)(dest.X / GridSize))));
start = map[startPos.X, startPos.Y];
endPos = (map[end.X, end.Y]);
openList.Add(map[startPos.X, startPos.Y]);
while (!endPos.closed)
{
num++;
openList = openList.OrderBy(p => p.F).ToList();
Note temp = null;
foreach (Note n in openList)
{
if (!closedList.Contains(n))
{
wtf += "number " + num + " = " + n.position.X + ", " + n.position.Y + "\r\n";
parenting(n.position, end);
n.closed = true;
temp = n;
break;
}
}
if (temp != null)
{
closedList.Add(temp);
openList.Remove(temp);
}
//File.WriteAllText("checking.txt", wtf);
//File.WriteAllText("listContent.txt", outp);
//File.WriteAllText("listCount.txt", openList.Count.ToString());
}
return path;
}
private void parenting(Point pos, Point dest)
{
checkNorth(pos, dest);
checkSouth(pos, dest);
checkEast(pos, dest);
checkWest(pos, dest);
//File.WriteAllText("DEBUGpos[" + pos.Y + ", " + pos.X + "].txt", values);
//if (NorthLeft && NorthRight && SouthLeft && SouthRight && EastLeft && EastRight && WestLeft && WestRight)
// Settings.exit = true;
}
private int GetH(Point v, Point endPos)
{
Point diff = new Point(v.X - endPos.X, v.Y - endPos.Y);
if (diff.X < 0) { diff.X *= 1; }
if (diff.Y < 0) { diff.Y *= 1; }
return Convert.ToInt16(diff.X + diff.Y);
}
private void checkNorth(Point pos, Point dest)
{
Point p = new Point(pos.X - 1, pos.Y);
if (map.XInRange(p.X))
{
if (map[p.X, p.Y].walkable && !map[p.X, p.Y].closed)
{
//values += p.X.ToString() + "," + p.Y.ToString() + " - " + map[p.X, p.Y].walkable + "\r\n";
if (map[p.X, p.Y] == endPos)
{
//File.WriteAllText("EndFound.txt", p.X + " - " + p.Y);
endPos.parent = pos;
endPos.closed = true;
closedList.Add(endPos);
path.Add(map[p.X, p.Y]);
while (!path.Contains(start))
{
path.Add(map[path[path.Count - 1].parent.X, path[path.Count - 1].parent.Y]);
}
path.Reverse();
}
else
{
if (map[p.X, p.Y].open == true)
{
if (map[pos.X, pos.Y].G + 10 < map[p.X, p.Y].G)
{
Settings.exit = true;
}
}
else
{
map[p.X, p.Y].open = true;
map[p.X, p.Y].parent = pos;
map[p.X, p.Y].H = GetH(p, dest);
map[p.X, p.Y].G = map[pos.X, pos.Y].G + 10;
map[p.X, p.Y].F = map[p.X, p.Y].G + map[p.X, p.Y].H;
NorthLeft = (map[p.X, p.Y - 1].walkable == true) ? true : false;
NorthRight = (map[p.X, p.Y + 1].walkable == true) ? true : false;
openList.Add(map[p.X, p.Y]);
}
}
}
else
{
NorthLeft = false;
NorthRight = false;
}
}
else
{
SouthLeft = false;
SouthRight = false;
}
//values += NorthLeft.ToString() + " " + NorthRight.ToString() + "\r\n";
}
private void checkSouth(Point pos, Point dest)
{
Point p = new Point(pos.X + 1, pos.Y);
if (p.X < 0)
{
SouthLeft = false;
SouthRight = false;
return;
}
//values += p.X.ToString() + "," + p.Y.ToString() + " - " + map[p.X, p.Y].walkable + "\r\n";
if (Enumerable.Range(0, map.GetLength(0)).Contains(p.X))
{
if (map[p.X, p.Y].walkable && !map[p.X, p.Y].closed)
{
if (map[p.X, p.Y] == endPos)
{
//File.WriteAllText("EndFound.txt", p.X + " - " + p.Y);
endPos.parent = pos;
endPos.closed = true;
closedList.Add(endPos);
path.Add(map[p.X, p.Y]);
while (!path.Contains(start))
{
path.Add(map[path[path.Count - 1].parent.X, path[path.Count - 1].parent.Y]);
}
path.Reverse();
}
else
{
if (map[p.X, p.Y].open == true)
{
if (map[pos.X, pos.Y].G + 10 < map[p.X, p.Y].G)
{
}
}
else
{
map[p.X, p.Y].open = true;
map[p.X, p.Y].parent = pos;
map[p.X, p.Y].H = GetH(p, dest);
map[p.X, p.Y].G = map[pos.X, pos.Y].G + 10;
map[p.X, p.Y].F = map[p.X, p.Y].G + map[p.X, p.Y].H;
if (Enumerable.Range(0, map.GetLength(1)).Contains(p.Y + 1))
SouthLeft = (map[p.X, p.Y + 1].walkable == true) ? true : false;
if (Enumerable.Range(0, map.GetLength(1)).Contains(p.Y - 1))
SouthRight = (map[p.X, p.Y - 1].walkable == true) ? true : false;
openList.Add(map[p.X, p.Y]);
}
}
}
else
{
SouthLeft = false;
SouthRight = false;
}
}
else
{
SouthLeft = false;
SouthRight = false;
}
//values += SouthLeft.ToString() + " " + SouthRight.ToString() + "\r\n";
}
private void checkEast(Point pos, Point dest)
{
Point p = new Point(pos.X, pos.Y + 1);
//File.WriteAllText("testEastpos.txt", p.X + " - " + p.Y + " -- " + map[p.X, p.Y].walkable);
//values += p.X.ToString() + "," + p.Y.ToString() + " - " + map[p.X, p.Y].walkable + "\r\n";
if (Enumerable.Range(0, map.GetLength(1)).Contains(p.Y))
{
if (map[p.X, p.Y].walkable && !map[p.X, p.Y].closed)
{
if (map[p.X, p.Y] == endPos)
{
//File.WriteAllText("EndFound.txt", p.X + " - " + p.Y);
endPos.parent = pos;
endPos.closed = true;
closedList.Add(endPos);
path.Add(map[p.X, p.Y]);
while (!path.Contains(start))
{
path.Add(map[path[path.Count - 1].parent.X, path[path.Count - 1].parent.Y]);
}
path.Reverse();
}
else
{
if (map[p.X, p.Y].open == true)
{
if (map[pos.X, pos.Y].G + 10 < map[p.X, p.Y].G)
{
}
}
else
{
map[p.X, p.Y].open = true;
map[p.X, p.Y].parent = pos;
map[p.X, p.Y].H = GetH(p, dest);
map[p.X, p.Y].G = map[pos.X, pos.Y].G + 10;
map[p.X, p.Y].F = map[p.X, p.Y].G + map[p.X, p.Y].H;
if (p.X - 1 >= 0)
EastLeft = (map[p.X - 1, p.Y].walkable == true) ? true : false;
else
EastLeft = false;
if (Enumerable.Range(0, map.GetLength(0)).Contains(p.Y))
{
EastRight = (map[p.X + 1, p.Y].walkable == true) ? true : false;
}
else
{ EastRight = false; }
openList.Add(map[p.X, p.Y]);
}
}
}
else
{
SouthLeft = false;
SouthRight = false;
}
}
else
{
EastLeft = false;
EastRight = false;
}
try
{
//File.WriteAllText("testEastSidepos.txt", (p.X - 1) + " - " + p.Y + " -- " + map[p.X - 1, p.Y].walkable + "\r\n" +
// (p.X + 1) + " - " + p.Y + " -- " + map[p.X + 1, p.Y].walkable);
}
catch
{ }
//values += EastLeft.ToString() + " " + EastRight.ToString() + "\r\n";
}
private void checkWest(Point pos, Point dest)
{
Point p = new Point(pos.X, pos.Y - 1);
if (Enumerable.Range(0, map.GetLength(1)).Contains(p.Y))
{
//values += p.X.ToString() + "," + p.Y.ToString() + " - " + map[p.X, p.Y].walkable + "\r\n";
if (map[p.X, p.Y].walkable && !map[p.X, p.Y].closed)
{
if (map[p.X, p.Y] == endPos)
{
//File.WriteAllText("EndFound.txt", p.X + " - " + p.Y);
endPos.parent = pos;
endPos.closed = true;
closedList.Add(endPos);
path.Add(map[p.X, p.Y]);
while (!path.Contains(start))
{
path.Add(map[path[path.Count - 1].parent.X, path[path.Count - 1].parent.Y]);
}
path.Reverse();
}
else
{
if (map[p.X, p.Y].open == true)
{
if (map[pos.X, pos.Y].G + 10 < map[p.X, p.Y].G)
{
}
}
else
{
map[p.X, p.Y].open = true;
map[p.X, p.Y].parent = pos;
map[p.X, p.Y].H = GetH(p, dest);
map[p.X, p.Y].G = map[pos.X, pos.Y].G + 10;
map[p.X, p.Y].F = map[p.X, p.Y].G + map[p.X, p.Y].H;
WestLeft = (map[p.X + 1, p.Y].walkable == true) ? true : false;
if (p.X - 1 >= 0)
WestRight = (map[p.X - 1, p.Y].walkable == true) ? true : false;
else
WestRight = false;
openList.Add(map[p.X, p.Y]);
}
}
}
else
{
WestLeft = false;
WestRight = false;
}
//values += WestLeft.ToString() + " " + WestRight.ToString() + "\r\n";
}
}
}
}
There is no need for the pathfinder to run while the monster is moving. It found a path, use that path.
A path must be recalculated, if the calculated path is blocked by an unpassable obstacle.
Then your zobie has to stop. The path is invalid anyway, it cannot move.
A path can be recalculated, if the environment changed in a way that suggests there will be a cheaper path available.
Only use the new path, if the full new path is cheaper then the remainder of the current path.
Edit:
Optimizing the pathfinder:
openList = openList.OrderBy(p => p.F).ToList();
This line is sorting the list every single time. You need a sorted list where it is sorted after inserting. As a quick fix, call openList.Sort() after inserting something. That may not be the best option though because it sorts the whole list while you already know that only a single element is unsorted.
The very same problem of finding a priority queue class in .NET is handled here
Your four north/east/south/west functions are code duplication. Check what they have in common and extract that into one common function. Your code will be just 25% of what it is now. That's not faster, but with less code, it's easier to see stuff.