Array goes out of index - unityscript

I have a problem in the below code:
var Directions : Vector3[]; //*
function FindNext(){
if(Set.length == 0){
Debug.Log("We're done.");
return;
}
var previous : Transform = Set[0];
var pScript : Cell = previous.GetComponent("Cell");
var next : Transform;
var nextScript : Cell;
var prevX : int = pScript.Position.x;
var prevZ : int = pScript.Position.z;
var randDirection : Vector3;
var randSeed : int = Random.Range(0,4);
var nextX : int;
var nextZ : int;
var counter : int;
do{
do{
randDirection = Directions[randSeed];
nextX = prevX+randDirection.x;
nextZ = prevZ+randDirection.z;
randSeed = (randSeed+1) % 4;
counter++;
if(counter > 4){
Set.RemoveAt(0);
previous.GetComponent.<Renderer>().material.color = Color.black;
yield WaitForEndOfFrame();
return;
}
}while(nextX < 0 || nextZ < 0 || nextX + 1 >= GridSize.x || nextZ + 1 >= GridSize.z);
next = GridArr[nextX,nextZ];
nextScript = next.GetComponent("Cell");
//nextScript.IsOpened = false;
}while(nextScript.IsOpened);
AddToSet(next);
DrawDebugLines(10, previous, next);
ClearWalls(previous, next);
yield WaitForEndOfFrame();
}
For some reason there's a problem with the array index, and I don't really know what it is.
Below is the error that I get:
IndexOutOfRangeException: Array index is out of range.
Grid+$FindNext$5+$.MoveNext () (at Assets/Scripts/Grid.js:74)
UnityEngine.MonoBehaviour:StartCoroutine_Auto(IEnumerator)
Grid:Update() (at Assets/Scripts/Grid.js:122)
I'm using UnityScript with Unity 5.

Well the solution was simple, like this program are running on Unity, the array that was Out of Range it's a public array with transforms, so to fix the problem, the only thing that need to do it's set the array values:
(0,1)(1,0)(1,1)(1,0)
This values are because the array must contain the four possible direction in a maze.

Related

GLSL math conditional AND

Maybe I'm not understanding the language or maybe the compiler is doing some kind of black magic but this code is not identical if I uncomment the comment which surprises me because to accept the conditional that should be the value of the variable :
`
while (distance < tMax) {
coords = uvec3(-1, -1, -1);
int active_voxel = volume_data_box_get_coords_from_point(
mi.block, first_prim_offset, mi.min.xyz, mi.max.xyz,
mi.slices_by_dimension, mi.memory_size, mi.voxel_size, hit, coords);
if ((active_voxel == 1) && (coords.x == 0) && (coords.y == 0) &&
(coords.z == 0)) {
// coords.x = 0;
// coords.y = 0;
// coords.z = 0;
bool are_extents = volume_data_box_get_extents_from_coords(
mi.block, first_prim_offset, mi.min.xyz, mi.slices_by_dimension, mi.memory_size,
mi.voxel_size, coords, voxel_extents);
if (are_extents) {
s = intersectRayOBB(ray.origin, ray.direction, mi.transform,
voxel_extents.min, voxel_extents.max);
tHit = s.t;
voxel_uv = s.uv;
hitKind = 1;
break;
}
}
// Update hit point from previous point plus direction multiplied by
// voxel size
hit += ray.direction * mi.voxel_size;
// Calculate distance between new hit point and ray origin
distance = length(hit - ray.origin);
}
`
I hope someone can clarify what is going on. Thanks!
The evaluated value is different from the expected one.

How can I make sure my RNG numbers are unique?

I'm trying to select 2 random items out of a list using the RNG class. The problem is occasionally I get the same 2 numbers and I'd like them to be unique. I tried using a while loop to get another number if the it's the same as the last one but adding even a simple while loop results in an "Exceeded prepaid gas" error. What am I not understanding?
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
for(let i = 0; i < numItemsWanted; i++) {
var r = rng.next()
while (r == rng.last()) {
r = rng.next()
}
newList.push(oldList[r])
}
Working:
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
newList.push(oldList[r])
last = r
r = rng.next()
while (r == last) {
r = rng.next()
}
}
this is about near-sdk-as, the smart contract development kit for AssemblyScript on the NEAR platform
you can see how RNG is used in this example
https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13
class Lottery {
private chance: f64 = 0.20
play(): bool {
const rng = new RNG<u32>(1, u32.MAX_VALUE);
const roll = rng.next();
logging.log("roll: " + roll.toString());
return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
}
}
and how the constructor is implemented here:
https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152
the first argument is the length of the buffer holding random numbers generated from the seed. you can use the next() method to get more numbers from this buffer with each call
export class RNG<T> {
constructor(len: u32, public max: u32 = 10_000) {
let real_len = len * sizeof<T>();
this.buffer = math.randomBuffer(real_len);
this._last = this.get(0);
}
next(): T {}
}
If you remove the item from oldList once picked, it would be imposible to picked it again.
Another aproach is to shuffle your oldList and then pick the first two items.

How to add settings to snake game(Processing)?

Im trying to add settings to a snake game made in processing. I want to have something like easy, normal and hard or something along the lines of that and change the speed and maybe size of the grid. If anyone coudl explain how to id greatly appreciate it!
ArrayList<Integer> x = new ArrayList<Integer>(), y = new ArrayList<Integer>();
int w = 30, h = 30, bs = 20, dir = 2, applex = 12, appley = 10;
int[] dx = {0,0,1,-1}, dy = {1,-1,0,0};
boolean gameover = false;
void setup() {
size(600,600);
x.add(5);
y.add(5);
}
void draw() {
background(255);
for(int i = 0 ; i < w; i++) line(i*bs, 0, i*bs, height); //Vertical line for grid
for(int i = 0 ; i < h; i++) line(0, i*bs, width, i*bs); //Horizontal line for grid
for(int i = 0 ; i < x.size(); i++) {
fill (0,255,0);
rect(x.get(i)*bs, y.get(i)*bs, bs, bs);
}
if(!gameover) {
fill(255,0,0);
rect(applex*bs, appley*bs, bs, bs);
if(frameCount%5==0) {
x.add(0,x.get(0) + dx[dir]);
y.add(0,y.get(0) + dy[dir]);
if(x.get(0) < 0 || y.get(0) < 0 || x.get(0) >= w || y.get(0) >= h) gameover = true;
for(int i = 1; i < x.size(); i++) if(x.get(0) == x.get(i) && y.get(0) == y.get(i)) gameover = true;
if(x.get(0)==applex && y.get(0)==appley) {
applex = (int)random(0,w);
appley = (int)random(0,h);
}else {
x.remove(x.size()-1);
y.remove(y.size()-1);
}
}
} else {
fill(0);
textSize(30);
text("GAME OVER. Press Space to Play Again", 20, height/2);
if(keyPressed && key == ' ') {
x.clear(); //Clear array list
y.clear(); //Clear array list
x.add(5);
y.add(5);
gameover = false;
}
}
if (keyPressed == true) {
int newdir = key=='s' ? 0 : (key=='w' ? 1 : (key=='d' ? 2 : (key=='a' ? 3 : -1)));
if(newdir != -1 && (x.size() <= 1 || !(x.get(1) ==x.get(0) + dx[newdir] && y.get (1) == y.get(0) + dy[newdir]))) dir = newdir;
}
}
You need to break your problem down into smaller steps:
Step one: Can you store the difficulty in a variable? This might be an int that keeps track of a level, or a boolean that switches between easy and hard. Just hardcode the value of that variable for now.
Step two: Can you write your code so it changes behavior based on the difficulty level? Use the variable you created in step one. You might use an if statement to check the difficulty level, or maybe the speed increases over time. It's completely up to you. Start out with a hard-coded value. Change the value to see different behaviors.
Step three: Can you programatically change that value? Maybe this requires a settings screen where the user chooses the difficulty, or maybe it gets more difficult over time. But you have to do the first two steps before you can start this step.
If you get stuck on a specific step, then post an MCVE and we'll go from there.

Generate several random numbers, one of which must be the correct answer to a sum?

I have created a Space Invaders game in which the player must shoot an asteroid which displays a random number. A sum will also be randomly generated at the start of the scene. Once the player shoots an asteroid the scene reloads, with points awarded for correct answers.
The problem I am having is that I need at least one asteroid to display the correct answer. I am currently achieving this by reloading the scene until an asteroids number matches the answer to the sum. This can take quite a few reloads and looks really bad. Is there a better way to achive this which will look better and be more efficient. I have included my effort below. I appreciate any comments. Thanks!
Script for checking the correct answer and reloading the scene.
#pragma strict
function Start ()
{
}
{
if (
Asteroid1_Script.asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid2_Script.asteroid2Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid3_Script.asteroid3Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid4_Script.asteroid4Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid5_Script.asteroid5Value != (Sum_Script.sumA - Sum_Script.sumB)
)
{
Application.LoadLevel("L1");
}
}
Script for randomly generating the sum.
#pragma strict
static var sumA :int = 0;
static var sumB :int = 0;
function Start ()
{
var newSumA = Random.Range(6,10);
sumA = newSumA;
var newSumB = Random.Range(1,6);
sumB = newSumB;
}
function Update () {
//Question Output.
guiText.text = sumA.ToString() + " - " + sumB.ToString()+ " =";
}
Script for generating an asteroids random number.
#pragma strict
var mainCam: Camera;
static var asteroid1Value : int = 0;
var asteroid1 : Transform;
var Asteroid1Style : GUIStyle;
function Start ()
{
var newAsteroid1Value = Random.Range(0,10);
asteroid1Value = newAsteroid1Value;
asteroid1.position.x = mainCam.ScreenToWorldPoint (new Vector3 (160f, 0f, 0f)).x;
asteroid1.position.y = mainCam.ScreenToWorldPoint (new Vector3 (0f, 450f, 0f)).y;
}
function OnGUI()
{
var point = Camera.main.WorldToScreenPoint(transform.position);
GUI.Label(new Rect(point.x, Screen.currentResolution.height - point.y - 530, 110, 100), asteroid1Value.ToString(), Asteroid1Style);
}
function OnCollisionEnter(col : Collision)
{
if(asteroid1Value == (Sum_Script.sumA - Sum_Script.sumB))
{
Destroy(gameObject);
Score_Script.score ++;
}
if(asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB))
{
Score_Script.score --;
}
}
Do as you are doing, generate 5 random numbers for your asteroids.
Then generate a random number between 1 and 5, this is your random asteroid, and then set its value to the answer. (sumA - sumB)
You just need to abstract your logic.
The best argument I can make is, simply put, build your random numbers before you build your asteroids.
That way, you always have a correct one.
I would simply code:
function start(){
var x = 5 //X being whatever number of asteroids you wish.
var a = new Array();
for(var i=0; i<x; i++){
a[i] = Random.Range(0,10);
}
for( i in a){ buildAsteroid(a[i]) }
}
And... if the number matches, success.

Precision error in JScript?

I'm a jscript newbie and I've a problem.
I'm writing a script to validate an IBAN bank account number in Belgium. I need to replace some letters by their position in a searchstring and afterwards I convert this string into a number to take the modulo 97 test.
The first part goes well, but afterwards with the conversion from string to number, 10 is added to my number. I don't know what I'm doing wrong.
function checkIBAN()
{
var iban = crmForm.all.fp_iban.DataValue;
if (iban != null)
{
iban = iban.substring(4) + iban.substring(0, 4);
iban = iban.toUpperCase();
var searchString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var pos;
var tmp = '';
for (x = 0; x < iban.length; x++) {
pos = searchString.search(RegExp(iban.charAt(x),'i'));
if (pos == -1)
return false;
else
tmp += pos.toString();
}
alert(tmp); // Here my value is 735320036532111490
var nr =parseInt(tmp);
alert(nr); // Now my value seems to be 735320036532111500
alert(nr % 97);
if (nr % 97 != 1)
{
alert('IBAN number is not correct !');
}
}
}
Yes, 735320036532111490 is simply too great a value to store in an int. It'll always be rounded:
alert(735320036532111490 / 10);
// alerts 73532003653211150
Here's a solution that might work for you.
Always specify the radix when using parseInt.
var nr =parseInt(tmp, 10);
For reference information: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt

Resources