Scrolling through an array - arrays

So I have a project in GameMaker, which has a chatbox. The messages for this are stored in an array. I would like to be able to scroll through this array, so I can view earlier chat messages.
This is what I currently have:
Create Event
chatLog[0] = "";
chatIndex = 0;
Step Event
if (chatIndex > 0) {
if (mouse_wheel_down()) {
chatIndex--;
}
}
if (chatIndex < array_length_1d(chatLog) - 1) {
if (mouse_wheel_up()) {
chatIndex++;
}
}
var _maxLines = 5;
for (i = 0; i < _maxLines; i++) {
if (i > (array_length_1d(chatLog) - 1)) { exit; }
var _chatLength = array_length_1d(chatLog) - 1;
draw_text(0, 50 - chatHeight, chatLog[_chatLength - i + chatIndex]);
}

First, for convenience of being able to add messages to front / remove them from the back (once there are too many), let's suppose that the log is a list, item 0 being the newest message,
chatLog = ds_list_create();
chatIndex = 0;
for (var i = 1; i <= 15; i++) {
ds_list_insert(chatLog, 0, "message " + string(i));
}
then, the Step Draw event can use information from the list to clamp scroll offset range and draw items:
var maxLines = 5;
// scrolling:
var dz = (mouse_wheel_up() - mouse_wheel_down()) * 3;
if (dz != 0) {
chatIndex = clamp(chatIndex + dz, 0, ds_list_size(chatLog) - maxLines);
}
// drawing:
var i = chatIndex;
var _x = 40;
var _y = 200;
repeat (maxLines) {
var m = chatLog[|i++];
if (m == undefined) break; // reached the end of the list
draw_text(_x, _y, m);
_y -= string_height(m); // draw the next item above the current one
}
live demo

Related

The cycle does not fully display all the elements

I make a grid of buttons as in the calendar, but for some reason not all of them appear
First, I loop through the array, then fill it with elements and display them, and if the loop variable reaches 7 then I lower the rendering of the buttons by 40 pixels to the bottom
It turns out like this
It should be something like this
public partial class Form1 : Form
{
Button[] January = new Button[31];
int XMounth = 400;
int YMounth = 100;
public Form1()
{
InitializeComponent();
for (int i = 1; i < January.Length; i++)
{
January[i] = new Button
{
Location = new Point(XMounth,YMounth),
Size = new Size(30, 30),
Text = Convert.ToString(i),
BackColor = Color.Orange
};
XMounth += 40;
if(i >= 7)
{
XMounth = 400;
YMounth = 140;
}
if (i >= 14)
{
XMounth = 400;
YMounth = 180;
}
if (i >= 21)
{
XMounth = 400;
YMounth = 220;
}
if (i >= 27)
{
XMounth = 400;
YMounth = 260;
}
this.Controls.Add(January[i]);
}
}
}
The conditions like i >= 7 are true not just once but for every number >= 7, so you reset XMounth to 400 for every number in the loop for 7 and above.
You can do this once for every specific row-break or just shorten this using modulo:
for (int i = 1; i < January.Length; i++)
{
January[i] = new Button
{
...
};
XMounth += 40;
if(i % 7 == 0) { XMounth = 400; YMounth += 40; }
this.Controls.Add(January[i]);
}

My for loop won't display my object, but no errors show up

For some reason my for loop isn't working, the enemies won't spawn and nothing appears in the Output when I used trace. However, there also is no error, so I'm wondering what the issue is.
Here is my code:
var playerX = 0;
var playerY = 0;
var mapWidth = 5000;
var mapHeight = 5000;
//enemy
var myEnemies:Array = new Array();
var enemySprite:Sprite;
var Enemy:enemy;
var enemyCount:int = 0;
//event listeners
stage.addEventListener(Event.ENTER_FRAME, spawnEnemies);
//spawn enemies
function spawnEnemies(spawn:Event) {
if (enemyCount < 20) {
for (var i = 0; i < myEnemies.length; i++) {
enemySprite = new Sprite();
this.addChild(enemySprite);
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
enemySprite.addChild(Enemy);
enemyCount++;
myEnemies[enemyCount] = enemySprite;
trace(myEnemies.length);
}
stage.addEventListener(Event.ENTER_FRAME, moveEnemy);
}
}
//move the enemies
function moveEnemy(enemyMovement:Event){
for (var k = 0; k < myEnemies.length; k++) {
trace("move enemy");
if (myEnemies[k].y > playerY) {
myEnemies[k].y -= 1;
myEnemies[k].rotation = 0;
}
else if (myEnemies[k].x < playerX) {
myEnemies[k].x += 1;
myEnemies[k].rotation = 90;
}
else if (myEnemies[k].y < playerY) {
myEnemies[k].y += 1;
myEnemies[k].rotation = 180;
}
else {
myEnemies[k].x -= 1;
myEnemies[k].rotation = 270;
}
}
}
Thank you for your help!
OK, I did not work with AS3 for a long time, but... Why do you expect new enemies to be created if myEnemies length is 0?
Also, you created two different ENTER_FRAME functions and there is no need to do that. Create only one function and call it for exmaple update:
private function update(e:event)
{
}
stage.addEventListener(Event.ENTER_FRAME, update);
You should not create new sprites using for loop inside ENTER_FRAME function, because this function runs 30 or more times in a second.
Create for loop inside "init" or "create" function, unless you want to update code on each frame.
Add 10 enemies:
for (var i = 0; i < 10; i++) {
Enemy = new enemy();
Enemy.x = (Math.random() * this.width);
Enemy.y = (Math.random() * this.height);
this.addChild(Enemy);
// add it to array
myEnemies.push(Enemy);
}
You cannot use myEnemies to create new Enemy sprite because it's empty, so you create 0 enemies. If you want to create 10 enemies use this code, or simple change number 10 to any number you want.

My if-statement doesn't work

It's either going to be "Riktig, bokstaven forekommer" for right letter chosen or otherwise. What have i done wrong, when i start it now none of the Messages show.
btnStart.addEventListener(MouseEvent.CLICK, start);
var feil:Array = new Array ;
var riktig:Array = new Array ;
var bokstav:Array = new Array ;
bokstav[0] = "b";
bokstav[1] = "r";
bokstav[2] = "e";
bokstav[3] = "v"
var txtBokstav:TextField = new TextField( );
txtBokstav.maxChars = 1;
txtBokstav.restrict = "a-z æ ø å";
txtBokstav.type = flash.text.TextFieldType.INPUT;
addChild(txtBokstav);
function start(evt)
{
var bokstavInn:String = String(txtBokstav.text);
if (txtBokstav.text.length == 1)
{
if (bokstav.indexOf(bokstavInn) >= 0)
{
txtUtskrift.text = "Riktig, bokstaven forekommer";
riktig.push(bokstavInn);
for (var i = 0; i < riktig.length; i++)
{
txtUtskrift.appendText(riktig[i] + ", ");
}
}
else
{
txtUtskrift.text = "Feil, bokstaven forekommer ikke";
feil.push(bokstavInn);
for (var l = 0; l < feil.length; l++)
{
txtUtskrift.appendText(feil[l] + ", ");
}
}
}
}
1) Are you sure that txtUtskrift is on the Stage and visible?
2) Make sure that start() is being called (use a breakpoint or trace)
3) As askmozo suggests, place trace statements in the possible flow of execution. So, at the beginning of the start function, and within each possible if condition. You might add an else for the text.length test:
function start( evt )
{
trace( "start()..." );
if (txtBokstav.text.length == 1)
{
// ... what you already have
}
else
{
trace( "txtBokstav length not valid:", txtBokStav.text.length );
}
trace( "...start()" );
}

Issue with accessing parts of the array

I am trying to simply generate parts of an array with certain buttons. the code is not really working properly.
The code is as follows:
import flash.events.MouseEvent;
var clock_01: Clock_one = new Clock_one ();
var clock_02: Clock_two = new Clock_two ();
var clock_03: Clock_three = new Clock_three ();
var clock_04: Clock_four = new Clock_four ();
var socket_one:socket;
var clock_x_position = 100;
var clock_y_position = 100;
var clock_Array: Array = new Array ();
clock_Array.push( clock_01,clock_02,clock_03,clock_04);
var clock_counter = 2;
var v = 0;
var c = 0;
clock_display();
function clock_display()
{
for (v; v < clock_counter; v++)
{
addChild(clock_Array[v]);
clock_Array[v].x = clock_x_position;
clock_Array[v].y = clock_y_position;
clock_y_position += 300;
trace( clock_Array [v]);
c = 0;
trace(v);
}
}
go_previous.addEventListener(MouseEvent.CLICK, go_back);
go_next.addEventListener(MouseEvent.CLICK, go_forward);
function go_back(l:MouseEvent)
{
v -= 2;
trace("The v after subtraction of 2" + v);
trace("Going Previous Function Starts ----------------");
for (v; v < clock_counter; v++)
{
removeChild(clock_Array[v]);
trace("The v after child removal" + v);
c++;
if (c == 2)
{
v -= 4;
trace("The v after subtraction in previous function is " + v);
clock_y_position = 100;
clock_counter -= 2;
trace("The clock counter in previous function is" + clock_counter);
clock_display();
}
}
}
function go_forward(l:MouseEvent)
{
v -= 2;
trace("Going Forwarf Function");
for (v; v < clock_counter; v++)
{
removeChild(clock_Array[v]);
trace("The v after subtraction in forward function is " + v);
trace("it atleast goes here");
c++;
if (c == 2)
{
v += 1;
clock_y_position = 100;
clock_counter += 2;
trace("The clock counter is" + clock_counter);
trace("The V is " +v);
clock_display();
}
}
}
Under the go_back function the v is not really getting subtracted by 2 as it is needed to. That's what it shows in the trace anyway. Can somebody please help me out with it?
Try the code below and do let me know if it works.
Pay attention to variable clock_Array_current_position.
It keeps the pointer to array element where your code is at.
import flash.events.MouseEvent;
var clock_01: Clock_one = new Clock_one ();
var clock_02: Clock_two = new Clock_two ();
var clock_03: Clock_three = new Clock_three ();
var clock_04: Clock_four = new Clock_four ();
var socket_one:socket;
var clock_x_position = 100;
var clock_y_position = 100;
var clock_Array: Array = new Array ();
clock_Array.push(clock_01,clock_02,clock_03,clock_04);
var clock_counter = 2;
var clock_Array_current_position = 0;
clock_display();
function clock_display()
{
var i = 0;
for (i; i < clock_counter; i++)
{
addChild(clock_Array[clock_Array_current_position + i]);
clock_Array[clock_Array_current_position+i].x = clock_x_position;
clock_Array[clock_Array_current_position+i].y = clock_y_position;
clock_y_position += 300;
}
}
function clock_remove()
{
var i = 0;
for (i; i < clock_counter; i++)
{
removeChild(clock_Array[clock_Array_current_position+i]);
}
}
go_previous.addEventListener(MouseEvent.CLICK, go_back);
go_next.addEventListener(MouseEvent.CLICK, go_forward);
function go_back(l:MouseEvent)
{
if(clock_Array_current_position > 0)
{
clock_remove();
clock_Array_current_position -= clock_counter;
clock_y_position = 100;
clock_display();
}
}
function go_forward(l:MouseEvent)
{
if(clock_Array_current_position < clock_Array.length-clock_counter)
{
clock_remove();
clock_Array_current_position += clock_counter;
clock_y_position = 100;
clock_display();
}
}

AS3 - Remove spaces from an array for word game

I'm building a word search game using the following AS3 code. My problem is I need to have spaces in my array of words, so that I can have things like states names, but I need the spaces removed before the words go into the puzzle.
The other concern is also that when a person selects a word from the puzzle will it still match the word in the list even though the word in the list still has a space.
I've struggled with this for a few days now and could use some help.
I've pasted all appropriate code below, I believe. Thanks.
Rich
// words and grid
private var wordList:Array;
private var usedWords:Array;
private var grid:Array;
// sprites
private var letterSprites:Sprite;
private var wordsSprite:Sprite;
wordList = ("New York,New Jersey,South Carolina,North Carolina").split(",");
// set up the sprites
gameSprite = new Sprite();
addChild(gameSprite);
letterSprites = new Sprite();
gameSprite.addChild(letterSprites);
wordsSprite = new Sprite();
gameSprite.addChild(wordsSprite);
// array of letters
var letters:Array = placeLetters();
// create word list fields and sprites
for(var i:int=0;i<usedWords.length;i++) {
var newWord:TextField = new TextField();
newWord.defaultTextFormat = letterFormatForList;
if(i < 20){ // first list
newWord.x = listXposition;
newWord.y = i*spacingForList+listYposition;
} else { // second list
newWord.x = listXposition + 130;
newWord.y = i*spacingForList+listYposition - (20 * 19);
}
newWord.width = 135;
newWord.height = spacingForList;
newWord.text = usedWords[i];
newWord.selectable = false;
wordsSprite.addChild(newWord);
}
// set game state
dragMode = "none";
numFound = 0;
}
// place the words in a grid of letters
public function placeLetters():Array {
// create empty grid
var letters:Array = new Array();
for(var x:int=0;x<puzzleSize;x++) {
letters[x] = new Array();
for(var y:int=0;y<puzzleSize;y++) {
letters[x][y] = "*";
}
}
// make copy of word list
var wordListCopy:Array = wordList.concat();
usedWords = new Array();
// make 1000 attempts to add words
var repeatTimes:int = 1000;
repeatLoop:while (wordListCopy.length > wordsLeft) {
if (repeatTimes-- <= 0) break;
// pick a random word, location and direction
var wordNum:int = Math.floor(Math.random()*wordListCopy.length);
var word:String = wordListCopy[wordNum].toUpperCase();
x = Math.floor(Math.random()*puzzleSize);
y = Math.floor(Math.random()*puzzleSize);
var dx:int = Math.floor(Math.random()*3)-1;
var dy:int = Math.floor(Math.random()*3)-1;
if ((dx == 0) && (dy == 0)) continue repeatLoop;
// check each spot in grid to see if word fits
letterLoop:for (var j:int=0;j<word.length;j++) {
if ((x+dx*j < 0) || (y+dy*j < 0) || (x+dx*j >= puzzleSize) || (y+dy*j >= puzzleSize)) continue repeatLoop;
var thisLetter:String = letters[x+dx*j][y+dy*j];
if ((thisLetter != "*") && (thisLetter != word.charAt(j))) continue repeatLoop;
}
// insert word into grid
insertLoop:for (j=0;j<word.length;j++) {
letters[x+dx*j][y+dy*j] = word.charAt(j);
}
// remove word from list
wordListCopy.splice(wordNum,1);
usedWords.push(word);
}
// fill rest of grid with random letters
for(x=0;x<puzzleSize;x++) {
for(y=0;y<puzzleSize;y++) {
if (letters[x][y] == "*") {
letters[x][y] = String.fromCharCode(65+Math.floor(Math.random()*26));
}
}
}
return letters;
}
// player clicks down on a letter to start
public function clickLetter(event:MouseEvent) {
var letter:String = event.currentTarget.getChildAt(0).text;
startPoint = findGridPoint(event.currentTarget);
dragMode = "drag";
}
// player dragging over letters
public function overLetter(event:MouseEvent) {
if (dragMode == "drag") {
endPoint = findGridPoint(event.currentTarget);
// if valid range, show outline
outlineSprite.graphics.clear();
if (isValidRange(startPoint,endPoint)) {
drawOutline(outlineSprite,startPoint,endPoint,0xCCCCCC);
}
}
}
// mouse released
public function mouseRelease(event:MouseEvent) {
if (dragMode == "drag") {
dragMode = "none";
outlineSprite.graphics.clear();
// get word and check it
if (isValidRange(startPoint,endPoint)) {
var word = getSelectedWord();
checkWord(word);
}
}
}
// when a letter is clicked, find and return the x and y location
public function findGridPoint(letterSprite:Object):Point {
// loop through all sprites and find this one
for(var x:int=0;x<puzzleSize;x++) {
for(var y:int=0;y<puzzleSize;y++) {
if (grid[x][y] == letterSprite) {
return new Point(x,y);
}
}
}
return null;
}
// determine if range is in the same row, column, or a 45 degree diagonal
public function isValidRange(p1,p2:Point):Boolean {
if (p1.x == p2.x) return true;
if (p1.y == p2.y) return true;
if (Math.abs(p2.x-p1.x) == Math.abs(p2.y-p1.y)) return true;
return false;
}
// draw a thick line from one location to another
public function drawOutline(s:Sprite,p1,p2:Point,c:Number) {
var off:Point = new Point(offset.x+spacing/2, offset.y+spacing/2);
s.graphics.lineStyle(outlineSize,c);
s.graphics.moveTo(p1.x*spacing+off.x ,p1.y*spacing+off.y-3);
s.graphics.lineTo(p2.x*spacing+off.x ,p2.y*spacing+off.y-3);
}
// find selected letters based on start and end points
public function getSelectedWord():String {
// determine dx and dy of selection, and word length
var dx = endPoint.x-startPoint.x;
var dy = endPoint.y-startPoint.y;
var wordLength:Number = Math.max(Math.abs(dx),Math.abs(dy))+1;
// get each character of selection
var word:String = "";
for(var i:int=0;i<wordLength;i++) {
var x = startPoint.x;
if (dx < 0) x -= i;
if (dx > 0) x += i;
var y = startPoint.y;
if (dy < 0) y -= i;
if (dy > 0) y += i;
word += grid[x][y].getChildAt(0).text;
}
return word;
}
// check word against word list
public function checkWord(word:String) {
// loop through words
for(var i:int=0;i<usedWords.length;i++) {
// compare word
if (word == usedWords[i].toUpperCase()) {
foundWord(word);
}
// compare word reversed
var reverseWord:String = word.split("").reverse().join("");
if (reverseWord == usedWords[i].toUpperCase()) {
foundWord(reverseWord);
}
}
}
// word found, remove from list, make outline permanent
public function foundWord(word:String) {
sndSuccess=new success_sound();
sndSuccessChannel=sndSuccess.play(200);
so.data.totalWordsFound = so.data.totalWordsFound + 1;
so.flush();
// draw outline in permanent sprite
drawOutline(oldOutlineSprite,startPoint,endPoint,0xDDDDDD);
// find text field and set it to gray
for(var i:int=0;i<wordsSprite.numChildren;i++) {
if (TextField(wordsSprite.getChildAt(i)).text.toUpperCase() == word) {
TextField(wordsSprite.getChildAt(i)).textColor = 0x777777;
}
}
// see if all have been found
numFound++;
if (numFound == usedWords.length) {
if (so.data.difficulty == "Easy") {
so.data.easyWon = so.data.easyWon + 1;
}
if (so.data.difficulty == "Medium") {
so.data.mediumWon = so.data.mediumWon + 1;
}
if (so.data.difficulty == "Hard") {
so.data.hardWon = so.data.hardWon + 1;
}
so.flush();
endGame();
}
}
I'm hesitant to post an answer as I'm not really sure what's going on, but hopefully this info will help:
Keep your words in the arrays with spaces, that's a good idea. When you want to check against the words in your game, just convert both words to the same format using a function. eg:
var wordList:Array = ("New York,New Jersey,South Carolina,North Carolina").split(",");
var selectedWord:String = "NEWYORK";
// minWord converts all words to the same format of no spaces and all lower case.
function minWord(word:String):String {
return word.replace(/\s/g, "").toLowerCase();
}
// this loop checks all the words from your array against the selectedWord.
for each(var word:String in wordList) {
trace(minWord(word) + " == " + minWord(selectedWord) + "; ", minWord(word) == minWord(selectedWord));
}
Hope that helps!

Resources