I have done a console game called "Labyrinth", now I want to bring it to Windows Forms, but I have some problems and exceptions and I can't understand how to make it work.
So, here is functional for printing field in console:
Base class Cell(it has children, like Wall, Door,Key,Empty, Player)
abstract class Cell
{
protected ConsoleColor foregroundColor;
protected ConsoleColor backgroundColor;
protected char symbol;
public Cell(ConsoleColor foregroundColor = ConsoleColor.White,
ConsoleColor backgroundColor = ConsoleColor.Black,
char symbol = ' ')
{
this.foregroundColor = foregroundColor;
this.backgroundColor = backgroundColor;
this.symbol = symbol;
}
public virtual void Draw()
{
Console.ForegroundColor = foregroundColor;
Console.BackgroundColor = backgroundColor;
Console.Write(symbol);
}
}
Here is class FileStorer that works with file(reads level from .txt file) and fills the array string[] field
class FileStorer
{
private string path;
public string[] Result;
public FileStorer(string path)
{
this.path = path;
Result = new string[0];
ReadFile();
}
private void Add(string item)
{
string[] newStr = new string[Result.Length + 1];
for (int i = 0; i < Result.Length; i++)
{
newStr[i] = Result[i];
}
newStr[Result.Length] = item;
Result = newStr;
}
public void ReadFile()
{
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Add(line);
}
}
}
}
Class Field
class Field
{
private bool toggle_key = false;
private Cell[,] field;
public int Width
{
get { return field.GetLength(1); }
}
public int Height
{
get { return field.GetLength(0); }
}
public Field(int width, int height)
{
field = new Cell[height, width];
}
public Cell this[int x, int y]
{
get { return field[y, x]; }
set { field[y, x] = value; }
}
public void Print()
{
Console.SetCursorPosition(0, 0);
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
this[x, y].Draw();
}
Console.WriteLine();
}
}
public bool NotOutOfField(int x, int y)
{
return x >= 0 && x < Width && y >= 0 && y < Height;
}
public void MakeEmpty(int x, int y)
{
this[x, y] = new Empty();
}
public bool CanMakeStep(int x, int y)
{
if (NotOutOfField(x, y) && this[x, y] is Empty)
return true;
if (NotOutOfField(x, y) && this[x, y] is Key && !toggle_key)
{
toggle_key = true;
Key.count--;
return true;
}
if (NotOutOfField(x, y) && this[x, y] is Door && toggle_key)
{
toggle_key = false;
Door.count--;
return true;
}
return false;
}
}
Here is class LevelLoader that fills array Cell[,] with proper classes (Door,Key etc.)
class LevelLoader
{
private string[] field;
public LevelLoader(int level)
{
field = new FileStorer($"../../Levels/{level}.txt").Result;
}
public void LoadField(out Field cellField, out Player player)
{
cellField = new Field(field[0].Length, field.Length);
player = new Player(0, 0);
for (int y = 0; y < field.Length; y++)
{
for (int x = 0; x < field[y].Length; x++)
{
switch (field[y][x])
{
case '#':
cellField[x, y] = new Wall();
break;
case ' ':
cellField[x, y] = new Empty();
break;
case 'K':
cellField[x, y] = new Key();
break;
case 'D':
cellField[x, y] = new Door();
break;
case 'P':
player = new Player(x, y);
goto case ' ';
default:
break;
}
}
}
}
}
And finally in class Level I have methods that puts characters on field and prints them
private void PutCharactersOnField()
{
for (int y = 0; y < gameField.Height; y++)
{
for (int x = 0; x < gameField.Width; x++)
{
if (!(gameField[x, y] is Wall) && !((gameField[x, y] is Key)) && !((gameField[x, y] is Door)))
{
gameField[x, y] = new Empty();
}
}
}
gameField[player.X, player.Y] = player;
}
public void PrintLevel()
{
gameField.Print();
player.Draw();
LivesMessage();
if (Door.count == 0)
{
Win();
};
}
I have done some changes for winforms, and I got IndexOutOfRanfeExceprion, I can't understand what went wrong, so here are the same classes and functions but changed for Winforms.
Class Cell
public abstract class Cell
{
public string Path;
public Image Image;
public Cell(string path)
{
Path = path;
if (!File.Exists(Path))
{
throw new Exception("File does not exist: " + Path);
}
Image = new Bitmap(Path);
}
public virtual void Draw(Graphics gr, int j, int i, int side, int x, int y)
{
gr.DrawImage(this.Image, j * side + x, i * side + y, new Rectangle(new Point(0, 0), new Size(side, side)), GraphicsUnit.Pixel);
}
}
FileStorer wasn't modified.
Class Player
public class Player:Cell
{
public string path;
protected Direction direction;
public Image SpriteAnimation;
public int X, Y;
public Size Scale;
public int CurrentFrame = 2;
public int CurrentAnimation = 5;
public Image Part;
public int speed;
public Direction CurrentDirection
{
get { return direction; }
}
public Player() : base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png") { }
public Player(Size scale, int x, int y, Image spriteAnimation):base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png")
{
SpriteAnimation = spriteAnimation;
Scale = scale;
X = x;
Y = y;
speed = 2;
if (!File.Exists(Path))
{
throw new Exception("File does not exist: " + Path);
}
base.Image = new Bitmap(Path);
}
public Player(int x, int y) : base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png")
{
X = x;
Y = y;
}
public void Action()
{
switch (direction)
{
case Direction.Left:
CurrentAnimation = 1;
break;
case Direction.Up:
CurrentAnimation = 3;
break;
case Direction.Right:
CurrentAnimation = 0;
break;
case Direction.Down:
CurrentAnimation = 2;
break;
}
}
public void Static()
{
switch (direction)
{
case Direction.Left:
CurrentAnimation = 6;
break;
case Direction.Up:
CurrentAnimation = 8;
break;
case Direction.Right:
CurrentAnimation = 5;
break;
case Direction.Down:
CurrentAnimation = 7;
break;
}
}
public void Rotate(int dx, int dy)
{
if (dx == -speed)
direction = Direction.Left;
else if (dx == speed)
direction = Direction.Right;
else if (dy == -speed)
direction = Direction.Up;
else if (dy == speed)
direction = Direction.Down;
}
public void MakeStep(int dx, int dy)
{
X += dx;
Y += dy;
}
public void DrawAction(Graphics gr, int x, int y)
{
gr.DrawImage(SpriteAnimation, X + x, Y + y, new Rectangle(new Point(75 * CurrentFrame, 170 * CurrentAnimation), new Size(75, 170)), GraphicsUnit.Pixel);
}
public void DrawStatic(Graphics gr, int x, int y)
{
gr.DrawImage(SpriteAnimation, X + x, Y + y, new Rectangle(new Point(75 * CurrentFrame, 170 * (CurrentAnimation - 5)), new Size(75, 170)), GraphicsUnit.Pixel);
}
}
Class LevelLoader was modified juct for player cell
case 'P':
player = new Player(new Size(35, 75), 100, 100,player.Image);
goto case ' ';
Class Field
class Field
{
private bool toggle_key = false;
private readonly Cell[,] field;
public int Width
{
get { return field.GetLength(1); }
}
public int Height
{
get { return field.GetLength(0); }
}
public Field(int width, int height)
{
field = new Cell[height, width];
}
public Cell this[int x, int y]
{
get { return field[y, x]; }
set { field[y, x] = value; }
}
public void Print(Graphics gr, int side, int j, int i)
{
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
this[x, y].Draw(gr, x, y,side, j, i);
}
}
}
public bool NotOutOfField(int x, int y)
{
return x >= 0 && x < Width && y >= 0 && y < Height;
}
public void MakeEmpty(int x, int y)
{
this[x, y] = new Empty();
}
public bool CanMakeStep(int x, int y)
{
if (NotOutOfField(x, y) && this[x, y] is Empty)
return true;
if (NotOutOfField(x, y) && this[x, y] is Key && !toggle_key)
{
toggle_key = true;
Key.count--;
return true;
}
if (NotOutOfField(x, y) && this[x, y] is Door && toggle_key)
{
toggle_key = false;
Door.count--;
return true;
}
return false;
}
}
Here are Level class method PrintLevel,(PutCharactersOnField wasn't modified)
public void PrintLevel(Graphics gr)
{
gameField.Print(gr, mapSide,point.X, point.Y);
player.DrawStatic(gr, point.X,point.Y);
if (Door.count == 0)
{
Win();
};
}
I'm very new in this topic, but I want to deal with this issue.So, I need help, what is wrong, where I made a mistake?
**Exception was called in the stack of calls
Related
I have my unity project set up with a graph like this:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is Point)
{
Point p = obj as Point;
return this.X == p.X && this.Y == p.Y;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
int hash = 6949;
hash = hash * 7907 + X.GetHashCode();
hash = hash * 7907 + Y.GetHashCode();
return hash;
}
}
public override string ToString()
{
return "P(" + this.X + ", " + this.Y + ")";
}
}
public enum CellType
{
Empty,
Road,
Structure,
SpecialStructure,
None
}
public class Grid
{
public CellType[,] _grid;
private int _width;
public int Width { get { return _width; } }
private int _height;
public int Height { get { return _height; } }
public List<Point> _roadList = new List<Point>();
public List<Point> _specialStructure = new List<Point>();
public List<Point> _houseStructure = new List<Point>();
public Grid(int width, int height)
{
_width = width;
_height = height;
_grid = new CellType[width, height];
}
// Adding index operator to our Grid class so that we can use grid[][] to access specific cell from our grid.
public CellType this[int i, int j]
{
get
{
return _grid[i, j];
}
set
{
if (value == CellType.Road)
{
_roadList.Add(new Point(i, j));
}
if (value == CellType.SpecialStructure)
{
_specialStructure.Add(new Point(i, j));
}
if (value == CellType.Structure)
{
_houseStructure.Add(new Point(i, j));
}
_grid[i, j] = value;
}
}
And I'm instantiating a series of gameobjects using an L-System algorithm and adding their X and Z positions to the graph like this:
public Grid AddToGrid(Vector3Int position, string type)
{
//CellType parsed_enum = (CellType)System.Enum.Parse(typeof(CellType), type);
switch (type)
{
case "Structure":
placementGrid._houseStructure.Add(new Point((int)position.x, (int)position.z));
break;
case "SpecialStructure":
placementGrid._specialStructure.Add(new Point((int)position.x, (int)position.z));
break;
case "Road":
placementGrid._roadList.Add(new Point((int)position.x, (int)position.z));
break;
}
return placementGrid;
}
And then in one of my scripts I'm calling another function:
public List<Point> GetWakableAdjacentCells(int x, int y, bool isAgent)
{
List<Point> adjacentCells = GetAllAdjacentCells(x, y);
Debug.Log("Adjacent Cells"+ adjacentCells.Count);//3
Debug.Log("X"+x); //-1
Debug.Log("Y"+y);//1
for (int i = adjacentCells.Count - 1; i >= 0; i--)
{
Debug.Log(adjacentCells[i].X); //-1
Debug.Log(adjacentCells[i].Y);//2
if (IsCellWakable(_grid[adjacentCells[i].X, adjacentCells[i].Y], isAgent) == false)
{
adjacentCells.RemoveAt(i);
}
}
return adjacentCells;
}
But this says "index was outside the bounds of the array" at if condition. I've commented each relevant value next to the variables for ease.
The function this condition is checking is this:
public static bool IsCellWakable(CellType cellType, bool aiAgent = false)
{
Debug.Log("boo");
if (aiAgent)
{
return cellType == CellType.Road;
}
return cellType == CellType.Empty || cellType == CellType.Road;
}
What am I doing wrong?
is there a way to implement a grid in such a way way that minus values can be accessed?
Well you commented yourself
// -1
-> -1 can not be a valid index in c#.
If you want to have a wrap around you could probably do e.g.
public CellType this[int i, int j]
{
get
{
i = (i % _width) + _width) % _width;
j = (j % _height) + _height) % _height;
return _grid[i, j];
}
set
{
i = (i % _width) + _width) % _width;
j = (j % _height) + _height) % _height;
switch(value)
{
case CellType.Road:
_roadList.Add(new Point(i, j));
break;
case CellType.SpecialStructure:
_specialStructure.Add(new Point(i, j));
break;
case CellType.Structure:
_houseStructure.Add(new Point(i, j));
break;
}
_grid[i, j] = value;
}
}
This means of course that your grid is basically "infinite" and crossing the top boarder you will be at the bottom again etc.
I got some problem with my Tetris game on highscore, here's the game script
/// The width of the Grid...
public static int gridWidth = 10;
/// The weight of the Grid...
public static int gridWeight = 20;
/// The grid...
public static Transform[,] grid = new Transform[gridWidth, gridWeight];
public static bool startingAtLevelZero;
public static int startingLevel;
public int scoreOneLine = 50;
public int scoreTwoLine = 100;
public int scoreThreeLine = 400;
public int scoreFourLine = 1500;
public int currentLevel = 0;
private int numLinesCleared = 0;
public static float fallSpeed = 1.0f;
public AudioClip clearedLineSound;
public Text hud_score;
public Text hud_level;
public Text hud_lines;
private int numberOfRowsThisTurn = 0;
private AudioSource audioSource;
public static int currentScore = 0;
private GameObject previewTetromino;
private GameObject nextTetromino;
private bool gameStarted = false;
private int startingHighScore;
private int startingHighScore2;
private int startingHighScore3;
private Vector2 previewTetrominoPosition = new Vector2(-6.5f, 16);
// Start is called before the first frame update
void Start()
{
currentScore = 0;
hud_score.text = "0";
currentLevel = startingLevel;
hud_level.text = currentLevel.ToString();
hud_lines.text = "0";
SpawnNextTetromino();
audioSource = GetComponent<AudioSource>();
startingHighScore = PlayerPrefs.GetInt("highScore");
startingHighScore2 = PlayerPrefs.GetInt("highscore2");
startingHighScore3 = PlayerPrefs.GetInt("highscore3");
}
void Update()
{
UpdateScore();
UpdateUI();
UpdateLevel();
UpdateSpeed();
}
void UpdateLevel()
{
if ((startingAtLevelZero == true) || (startingAtLevelZero == false && numLinesCleared / 10 > startingLevel))
currentLevel = numLinesCleared / 10;
Debug.Log("current Level : " + currentLevel);
}
void UpdateSpeed()
{
fallSpeed = 1.0f - ((float)currentLevel * 0.1f);
Debug.Log("current Fall Speed : " + fallSpeed);
}
public void UpdateUI()
{
hud_score.text = currentScore.ToString();
hud_level.text = currentLevel.ToString();
hud_lines.text = numLinesCleared.ToString();
}
public void UpdateScore()
{
if (numberOfRowsThisTurn > 0)
{
if (numberOfRowsThisTurn == 1)
{
ClearedOneLine();
}
else if (numberOfRowsThisTurn == 2)
{
ClearedOneLine();
}
else if (numberOfRowsThisTurn == 3)
{
ClearedThreeLine();
}
else if (numberOfRowsThisTurn == 4)
{
ClearedFourLine();
}
numberOfRowsThisTurn = 0;
PlayLineClearedSound();
}
}
public void ClearedOneLine()
{
currentScore += scoreOneLine + (currentLevel * 20);
numLinesCleared++;
}
public void ClearedTwoLine()
{
currentScore += scoreTwoLine + (currentLevel * 25);
numLinesCleared += 2;
}
public void ClearedThreeLine()
{
currentScore += scoreThreeLine + (currentLevel * 30);
numLinesCleared += 3;
}
public void ClearedFourLine()
{
currentScore += scoreFourLine + (currentLevel * 40);
numLinesCleared += 4;
}
public void PlayLineClearedSound()
{
audioSource.PlayOneShot(clearedLineSound);
}
public void UpdateHighScore()
{
if (currentScore > startingHighScore)
{
PlayerPrefs.SetInt("highScore3", startingHighScore2);
PlayerPrefs.SetInt("highScore2", startingHighScore);
PlayerPrefs.SetInt("highscore", currentScore);
}
else if (currentScore > startingHighScore2)
{
PlayerPrefs.SetInt("highScore3", startingHighScore2);
PlayerPrefs.SetInt("highscore2", currentScore);
}
else if (currentScore > startingHighScore3)
{
PlayerPrefs.SetInt("highscore3", currentScore);
}
}
public bool CheckIsAboveGrid(Tetromino tetromino)
{
for (int x = 0; x < gridWidth; ++x)
{
foreach (Transform mino in tetromino.transform)
{
Vector2 pos = Round(mino.position);
if (pos.y > gridWeight - 1)
{
return true;
}
}
}
return false;
}
public bool IsFullRowAt (int y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid [x, y] == null)
{
return false;
}
}
numberOfRowsThisTurn++;
return true;
}
public void DeleteMinoAt(int y)
{
for (int x = 0; x < gridWidth; ++x)
{
Destroy(grid[x, y].gameObject);
grid[x, y] = null;
}
}
public void MoveRowDown (int y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid[x, y] != null)
{
grid[x,y -1] = grid[x, y];
grid[x, y] = null;
grid[x, y -1].position += new Vector3(0, -1, 0);
}
}
}
public void MoveAllRowsDown (int y)
{
for (int i = y; i < gridWeight; ++i)
{
MoveRowDown(i);
}
}
public void DeleteRow()
{
for (int y = 0; y < gridWeight; ++y)
{
if (IsFullRowAt(y))
{
DeleteMinoAt(y);
MoveAllRowsDown(y + 1);
--y;
}
}
}
public void UpdateGrid (Tetromino tetromino)
{
for (int y = 0; y < gridWeight; ++y)
{
for (int x = 0; x < gridWidth; ++x)
{
if (grid[x, y] != null)
{
if (grid[x,y].parent == tetromino.transform)
{
grid[x, y] = null;
}
}
}
}
foreach (Transform mino in tetromino.transform)
{
Vector2 pos = Round(mino.position);
if (pos.y < gridWeight)
{
grid[(int)pos.x, (int)pos.y] = mino;
}
}
}
public Transform GetTransformAtGridPosition (Vector2 pos)
{
if (pos.y > gridWeight -1)
{
return null;
}
else
{
return grid[(int)pos.x, (int)pos.y];
}
}
public void SpawnNextTetromino()
{
if (!gameStarted)
{
gameStarted = true;
nextTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), new Vector2(5.0f, 20.0f), Quaternion.identity);
previewTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
previewTetromino.GetComponent<Tetromino>().enabled = false;
}
else
{
previewTetromino.transform.localPosition = new Vector2(5.0f, 20.0f);
nextTetromino = previewTetromino;
nextTetromino.GetComponent<Tetromino>().enabled = true;
previewTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
previewTetromino.GetComponent<Tetromino>().enabled = false;
}
}
public bool CheckIsInsideGrid (Vector2 pos)
{
return ((int)pos.x >= 0 && (int)pos.x < gridWidth && (int)pos.y >= 0);
}
public Vector2 Round (Vector2 pos)
{
return new Vector2(Mathf.Round(pos.x), Mathf.Round(pos.y));
}
string GetRandomTetromino()
{
int randomTetromino = Random.Range(1, 8);
string randomTetrominoName = "Prefabs/Tetromino_T";
switch (randomTetromino)
{
case 1:
randomTetrominoName = "Prefabs/Tetromino_T";
break;
case 2:
randomTetrominoName = "Prefabs/Tetromino_Long";
break;
case 3:
randomTetrominoName = "Prefabs/Tetromino_Square";
break;
case 4:
randomTetrominoName = "Prefabs/Tetromino_J";
break;
case 5:
randomTetrominoName = "Prefabs/Tetromino_L";
break;
case 6:
randomTetrominoName = "Prefabs/Tetromino_S";
break;
case 7:
randomTetrominoName = "Prefabs/Tetromino_Z";
break;
}
return randomTetrominoName;
}
public void GameOver()
{
UpdateHighScore();
Application.LoadLevel("GameOver");
}
and here's the game menu script
public Text levelText;
public Text highScoreText;
public Text highScoreText2;
public Text highScoreText3;
// Start is called before the first frame update
void Start()
{
levelText.text = "0";
highScoreText.text = PlayerPrefs.GetInt("highscore").ToString();
highScoreText2.text = PlayerPrefs.GetInt("highscore2").ToString();
highScoreText3.text = PlayerPrefs.GetInt("highScore3").ToString();
}
public void PlayGame()
{
if (Game.startingLevel == 0)
Game.startingAtLevelZero = true;
else
Game.startingAtLevelZero = false;
Application.LoadLevel("tetris");
}
public void ChangedValue (float value)
{
Game.startingLevel = (int)value;
levelText.text = value.ToString();
}
public void LaunchGameMenu()
{
Application.LoadLevel("tetris menu");
}
When I got 1120 score in the Tetris game, it shows up in 2nd score instead of 3rd or 1st ,when I got 720 score, it doesn't show up in 3rd score, when I score 1300 It shows up in 2nd and 1120 in 3rd, but not in 1st, can somehow help me what is wrong?
It appears you have various typographical errors while typing the keys when accessing the player's PlayerPrefs. PlayerPrefs is case-sensitive.
↓↓↓
startingHighScore = PlayerPrefs.GetInt("highScore");
startingHighScore2 = PlayerPrefs.GetInt("highscore2");
startingHighScore3 = PlayerPrefs.GetInt("highscore3");
...
↓↓↓
highScoreText.text = PlayerPrefs.GetInt("highscore").ToString();
Consider the use of the nameof() command. The nameof() command allows you to treat a variable in-code as a string. This is SUPER helpful if you ever re-name the variable for example, the string will be renamed along with it. It also has the added bonus of giving you compilation errors if they are misspelled.
Example:
public Text levelText;
public Text highScoreText;
public Text highScoreText2;
public Text highScoreText3;
// Start is called before the first frame update
void Start()
{
levelText.text = "0";
highScoreText.text = PlayerPrefs.GetInt(nameof(highScoreText)).ToString();
highScoreText2.text = PlayerPrefs.GetInt(nameof(highScoreText2)).ToString();
highScoreText3.text = PlayerPrefs.GetInt(nameof(highScoreText3)).ToString();
}
So I made a little editor script that helps me create templates for a dungeon generator. But when I want to use the information saved in the ScriptableObject the array seems to throw a NullReferenceException.
This class creates a grid that is editable in the game view and then uses the next class to turn the information into a new ScriptableObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using RoomTypes;
using TileTypes;
public class CreateRoom : MonoBehaviour {
public GameObject tile;
public TileType curTileType;
public RoomType type;
public Tile[,] grid;
public int width;
public int height;
public TileButton[,] tileButtons;
private GameObject tileParent;
public void Create()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
grid[x, y] = new Tile( tileButtons[x, y].tileType ) ;
}
}
CreateSORoom.CreateRoom(type, grid, width, height);
}
public void CreateGrid()
{
tileButtons = new TileButton[width, height];
DeleteGrid();
FindObjectOfType<CreateRoomCamera>().SetCamera(width, height);
if (!tileParent) tileParent = new GameObject("TileParent");
grid = new Tile[width, height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
GameObject newTile = Instantiate(tile, tileParent.transform);
newTile.GetComponent<RectTransform>().anchoredPosition = new
Vector3(0.5f + x, 0.5f + y);
tileButtons[x, y] = newTile.GetComponent<TileButton>();
tileButtons[x, y].xCoord = x;
tileButtons[x, y].yCoord = y;
}
}
}
}
[CustomEditor(typeof(CreateRoom))]
public class CreateRoomEditor : Editor
{
public override void OnInspectorGUI()
{
CreateRoom createRoom = (CreateRoom)target;
base.OnInspectorGUI();
if (GUILayout.Button("Create Grid"))
{
createRoom.CreateGrid();
}
if (GUILayout.Button("Create Room"))
{
createRoom.Create();
}
}
}
This is the class that creates the Object.
using UnityEngine;
using UnityEditor;
using System.IO;
using RoomTypes;
using TileTypes;
public static class CreateSORoom
{
public static void CreateRoom(RoomType type, Tile[,] grid, int width, int
height)
{
Room room = ScriptableObject.CreateInstance<Room>();
string path = "Assets/LevelGeneration/RoomCreation/Rooms/";
string assetName = "";
if (type == RoomType.LeftRight) assetName = "LeftRight";
else if (type == RoomType.LeftDown) assetName = "LeftDown";
else if (type == RoomType.RightDown) assetName = "DownRight";
else if (type == RoomType.LeftUp) assetName = "LeftUp";
else if (type == RoomType.UpRight) assetName = "UpRight";
else if (type == RoomType.Start) assetName = "Start";
else if (type == RoomType.End) assetName = "End";
else if (type == RoomType.Bonus) assetName = "Bonus";
else if (type == RoomType.Empty) assetName = "Empty";
path += assetName;
if (Path.GetExtension(path) != "")
{
path = path.Replace(Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject)), "");
}
string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + assetName + width + "x" + height + ".asset");
room.Init(type, width, height, grid);
AssetDatabase.CreateAsset(room, assetPathAndName);
EditorUtility.SetDirty(room);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.FocusProjectWindow();
Selection.activeObject = room;
}
}
public class Room : ScriptableObject
{
public RoomType type;
public int width;
public int height;
public Tile[,] grid;
public void Init(RoomType _type, int _width, int _height, Tile[,] _grid)
{
type = _type;
width = _width;
height = _height;
grid = new Tile[width, height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
grid[x, y] = _grid[x, y];
}
}
}
}
The creation works fine as long as I dont exit the play mode. After exiting and entering the playmode again the array is not available but the other informations like the width and height are still saved.
Unity can't serialize 2D arrays. You need to use a 1D array [width * height] and access elements via [x + y * width].
I couldn't find any explanation for the line in a red rectangle, could anyone help me breaking it down?
The given interface defines an override for the indexer operator ([]). A simple example of use:
class Point
{
public int X { get; set; }
public int Y { get; set; }
}
class PointCollection
{
public List<Point> collection { get; set; }
public Point this[int x, int y]
{
get => collection.FirstOrDefault(item => item.X == x && item.Y == y);
}
}
And then:
PointCollection points = new PointCollection();
var item = points[100, 200];
Hope this answers to your question
public class MyImage : IImage
{
private IColor[,] imageData = null;
int w=0, h = 0;
public MyImage(int width, int height, IColor defaultColor)
{
//throw new NotImplementedException();
imageData = new IColor[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
imageData[i, j] = defaultColor;
}
}
}
public IColor this[int x, int y]
{
get
{
w = imageData.GetLength(0);
h = imageData.GetLength(1);
//throw new NotImplementedException();
if ((w > 0 && w > x) && (h > 0 && h > y))
return imageData[x, y];
else
return null;
}
set
{
//throw new NotImplementedException();
if ((w > 0 && w > x) && (h > 0 && h > y))
imageData[x, y] = value;
}
}
}
public interface IColor
{
}
public interface IImage
{
IColor this[int x, int y] { get; set; }
}
I am creating really simple pacman game as a homework. I am working in Visual Studio, in c#. The problem is, when I click run, only the winform shows with nothing on it. Can someone tell me what have I done wrong?
namespace pacman
{
public partial class Form1 : Form
{
Timer timer;
Pacman pacman;
static readonly int TIMER_INTERVAL = 250;
static readonly int WORLD_WIDTH = 15;
static readonly int WORLD_HEIGHT = 10;
Image foodImage;
bool[][] foodWorld;
public Form1()
{
InitializeComponent();
foodImage = Properties.Resources.orange_detoure;
DoubleBuffered = true;
newGame();
}
public void newGame()
{
pacman = new Pacman();
this.Width = Pacman.radius * 2 * (WORLD_WIDTH + 1);
this.Height = Pacman.radius * 2 * (WORLD_HEIGHT + 1);
foodWorld = new bool[WORLD_WIDTH][];
timer = new Timer();
timer.Interval = TIMER_INTERVAL;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
timer.Interval = TIMER_INTERVAL - 1;
if (TIMER_INTERVAL == 0)
{
timer.Stop();
}
pacman.Move(WORLD_WIDTH, WORLD_HEIGHT);
Invalidate();
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (Keys.Up != 0)
{
pacman.ChangeDirection("UP");
}
if (Keys.Down != 0)
{
pacman.ChangeDirection("DOWN");
}
if (Keys.Left != 0)
{
pacman.ChangeDirection("LEFT");
}
if (Keys.Right != 0)
{
pacman.ChangeDirection("RIGHT");
}
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.Clear(Color.White);
for (int i = 0; i < foodWorld.Length; i++)
{
for (int j = 0; j < foodWorld[i].Length; j++)
{
if (foodWorld[i][j])
{
g.DrawImageUnscaled(foodImage, j * Pacman.radius * 2 + (Pacman.radius * 2 - foodImage.Height) / 2, i * Pacman.radius * 2 + (Pacman.radius * 2 - foodImage.Width) / 2);
}
}
}
pacman.Draw(g);
}
}
}
And here is the class Pacman:
namespace pacman
{
public class Pacman
{
public enum dir {UP, DOWN, RIGHT, LEFT};
public float x { get; set; }
public float y { get; set; }
public string direction { get; set; }
static public int radius = 20;
public double speed { get; set; }
public bool open { get; set; }
public Brush brush = new SolidBrush(Color.Yellow);
public Pacman() {
this.x = 7;
this.y = 5;
this.speed = 20;
this.direction = Convert.ToString(dir.RIGHT);
this.open = false;
}
public void ChangeDirection(string direct)
{
// vasiot kod ovde
for (int i = 0; i < 3; i++) {
if(direct == Convert.ToString(dir.RIGHT))
{
direction = "RIGHT";
}
if (direct == Convert.ToString(dir.LEFT))
{
direction = "LEFT";
}
if (direct == Convert.ToString(dir.UP))
{
direction = "UP";
}
if (direct == Convert.ToString(dir.DOWN))
{
direction = "DOWN";
}
}
}
public void Move(float width, float height)
{
if (direction == Convert.ToString(dir.RIGHT))
{
x = x + 1;
if (x > width) {
x = 1;
}
}
else if (direction == Convert.ToString(dir.LEFT))
{
x = x - 1;
if (x < 0) {
x = 14;
}
}
else if (direction == Convert.ToString(dir.UP))
{
y = y + 1;
if (y > height) {
y = 1;
}
}
else if (direction == Convert.ToString(dir.DOWN))
{
y = y - 1;
if (y < 0) {
y = 14;
}
}
}
public void Draw(Graphics g)
{
if (!open) {
g.FillEllipse(brush, 7, 5, 15, 15);
}
}
}
}
It should look like this http://prntscr.com/70e0jt.
I will be grateful if someone can tell me what should I fix so it finally works..
Add this to your constructor:
this.Paint += Form1_Paint;
What is happening is that you made a Paint handler, but never assigned the paint event to handle it (that I can see, its possible that the event was assigned in the other partial part of the class).
The other problem is that you did not fully define the "food world" variable, you initialized the first rank, but not the second. You need to fully initialize this and set the booleans inside of it.