D3 import .csv to 2Darray & opacity change when hover - arrays

I'm currently writing a visualization via D3 and I hope you can help me out.
To get an idea of what I'm making you can view this link: https://dl.dropboxusercontent.com/u/56480311/Data-visualization/index.html
I'm facing two problems: the first is that I can't seem to place .csv data in a 2D array. I found multiplie tutorials about placing it in a normal array but the only solution I came up with if your data is in a table, is to use a 2D array. I couldn't find how to do this so what I thought would help:
var lines = []; //define lines as an array
//retrieve data from .csv file
d3.csv("https://dl.dropboxusercontent.com/u/56480311/Data-visualization/growth-prep.csv", function(data) {
lines = data.map(function(d) {
return d;
});
});
//create 2D array named myArray
var myArray = new Array(10);
for (var i = 0; i < 10; i++) {
myArray[i] = new Array(18);
}
//place each value of .csv file into myArray
for (var j = 0; j < lines.length; j++) {
var values = lines[j].split(";");
for (var k = 0; k < values.length; k++) {
myArray[k][j] = values[k];
}
}
This code doesn't work, however. Console keeps saying that the arrays are undefined and they're empty.
A second problem I'm facing is in visualizing the data. I sum three values that are next to each other (so for example dataset[0][0] + dataset[0][1] + dataset[0][2]). I draw this value as the width of a rectangle. On top of that, I want to draw three different rectangles each with the value of one of three. So in this case there is one rectangle consisting of dataset[0][0] + dataset[0][1] + dataset[0][2] and on top there is a rectangle showing data dataset[0][0], one showing data dataset[0][1] and a third showing data dataset[0][2]. I want the three smaller ones only to appear once the mouse hovers over the 'sum' / parent rectangle.
If you view the link you can see what I mean. Everything is already there, only the three smaller rectangles have opacity 0 so you don't see them yet (but you can find them via inspect elements).
I figured I could do this by setting the opacity of the three rectangles to 0 and to 1 once the mouse hovers. The best solution to me would be to place the three rectangles into one kind of div. Once the mouse hovers over it, its opacity is 1. Only I can't figure out how to easily give different class names without having to do it by hand for each rectangle separately. Does anyone know how to do this or else have a better solution to change the opacity of all three rectangles once the mouse hovers over the 'bigger' rectangle?
This is the code:
var dataset = [[6,6,3,3,3,0,6,6,0,12,6,6,0,0,18,6,3,3],[3,0,0,6,3,0,3,3,0,9,3,0,0,0,18,6,6,6],[3,0,3,6,3,3,6,0,3,9,6,3,0,0,15,6,6,6],[6,6,3,3,0,3,6,6,6,12,6,6,0,0,18,6,6,3],[6,6,0,6,0,0,6,6,6,12,6,6,0,0,24,6,6,0],[3,6,3,6,3,3,6,6,3,3,0,0,0,0,15,3,9,6],[3,3,0,3,0,3,3,3,3,9,3,0,0,0,15,6,3,9],[0,0,0,3,0,6,6,3,3,3,0,3,0,0,24,6,12,6],[6,6,3,6,0,0,9,9,6,12,6,6,0,0,15,3,3,3],[6,6,0,6,3,0,6,6,0,9,6,3,0,0,9,3,6,0]];
var h = 800;
var w = 800;
//create svg of 800x800px
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var xPos = 150;
for (var k = 0; k < 10; k++) { //loop through lines of array
var yPos = 40 + k*80;
for (var j = 0; j < 18; j++) { //loop through rows of array
var count = j + 1;
//assign data of three boxes to value1/value2/value3 with which we will later on draw three separate rectangles to visualize the data
if (count == 1 || count == 4 || count == 7 || count == 10 || count == 13 || count == 16) {
var value1 = dataset[k][j];
}
if (count == 2 || count == 5 || count == 8 || count == 11 || count == 14 || count == 17) {
var value2 = dataset[k][j];
}
if (count == 3 || count == 6 || count == 9 || count == 12 || count == 15 || count == 18) {
var value3 = dataset[k][j];
}
if (count % 3 ==0) {
var sum = dataset[k][j] + dataset[k][j-1] + dataset[k][j-2]; //count the three values to also draw one bigger rectangle of their sum
var rectangle = svg.append("rect")
.attr("x", xPos)
.attr("y", yPos)
.attr("width", sum*5)
.attr("height", 20)
.attr("fill", function(d) {
if (count == 3) {
return "LightSeaGreen";
}
else if (count == 6) {
return "MediumSeaGreen";
}
else if (count == 9) {
return "MediumSpringGreen";
}
else if (count == 12) {
return "LimeGreen";
}
else if (count == 15) {
return "ForestGreen"
}
else if (count == 18) {
return "GreenYellow"
}
});
for (var l = 0; l < 3; l++) { //draw three 'sub' rectangles on top of the one 'sum' rectangle. they should appear when the mouse hovers over their 'sum' rectangle
var rectangle2 = svg.append("rect")
.attr("class", "sqr")
.attr("x", function() {
if (l == 0) {
return xPos;
} else if (l == 1) {
return xPos + value1*5;
} else if (l == 2) {
return xPos + (value1+value2)*5;
}
})
.attr("y", yPos)
.attr("width", function() {
if (l == 0) {
return value1*5;
} else if (l == 1) {
return value2*5;
} else if (l == 2) {
return value3*5;
}
})
.attr("height", 20)
.attr("fill", function() {
if (l == 0) {
return "SteelBlue";
} else if (l == 1) {
return "aquamarine";
} else if (l == 2) {
return "SkyBlue";
}
})
.attr("opacity", 0); //in first instance the rectangles are not visible. Opacity should turn to 1 when the mouse hovers over their according div
}
if (sum > 0) {
xPos = xPos + sum*5 + 5;
}
}
}
xPos = 150;
}

Related

How can i stop the rotation of an object in an array? P5.JS

this is for a project in my p5.js class.
I have a class that creates a 3D shape and i call it in my draw function in a for loop. In this for loop i create the shape and it has a rotation. If i press the the "a" button, it creates a new shape. My problem is, that i want to stop the rotation of the previous shape when i create a new shape, but i can't find a solution.
this is my code:
let BLACK;
let GRAY;
let LIGHTGRAY;
let WHITE;
let RED;
let forms = [];
let coorX, coorY, coorZ, colour;
let COL = [];
let ran;
function setup() {
createCanvas(586, 810, WEBGL);
BLACK = color(0);
GRAY = color(70);
LIGHTGRAY = color(180);
WHITE = color(255);
RED = color(217, 4, 33);
COL = [BLACK, WHITE, GRAY, RED, RED\]
ran = random(0.01, 0.1)
}
function draw() {
background(80);
pointLight(250, 250, 250, 250);
for (let i = 0; i < forms.length; i++) {
newSpeed = 0.05 + i * ran
forms[i].create(newSpeed, 0.01);
if (forms.length > 1) {
rotateX(0);
}
}
if (forms.length > 10) {
//Array limited on 10 objects
forms.splice(0, 1)
}
}
function keyTyped() {
if (key === 'a') {
coorX = int(random(-100, 100))
coorY = int(random(-100, 100))
coorZ = int(random(-200, 200))
forms.push(new Shape(coorX, coorY, coorZ));
}
if (key === 'd') {
forms.pop()
}
}
class Shape {
constructor(posX, posY, posZ, colour) {
this.x = 50; //width
this.y = 50; //height
this.z = 50; // depth
this.x1 = 0;
this.y1 = 500;
this.z1 = 80;
this.posX = posX;
this.posY = posY;
this.posZ = posZ;
this.rand = int(random(0, 5));
this.colour = colour;
}
create (speed, rotation) {
//create a new shape
stroke(0);
strokeWeight(0);
push();
translate(this.posX, this.posY, this.posZ)
//rotate the shape
this.speed = speed;
this.rotation = rotation;
rotateX((frameCount * this.rotation) * speed)
rotateY((frameCount * this.rotation) * speed)
if (this.rand == 1) {
fill(RED)
box(50, 50, 50)
}
if (this.rand == 2) {
fill(LIGHTGRAY);
sphere(50, 10)
}
if (this.rand == 3) {
fill(WHITE);
cylinder(5, 280, 15)
}
if (this.rand == 4) {
fill(GRAY);
torus(90, 24, 3)
}
pop();
}
}
I tried separating the rotation and the creation function, but then it rotated the whole canvas and not the shapes individually.
In fact, in p5.js approach is completely different, and You need to analyze this example: https://p5js.org/examples/simulate-multiple-particle-systems.html
But, to solve Your problem in 'object style':
1 - You need to memorize state of the object, in this case the frameCount of the last frame when the key a was pressed,
2 - draw all shapes with memorized lastActiveFrame and one just with recent frameCount.
let BLACK;
let GRAY;
let LIGHTGRAY;
let WHITE;
let RED;
let forms = [];
let coorX, coorY, coorZ, colour;
let COL = [];
let ran;
function setup() {
createCanvas(586, 810, WEBGL);
BLACK = color(0);
GRAY = color(70);
LIGHTGRAY = color(180);
WHITE = color(255);
RED = color(217,4,33);
COL = [BLACK, WHITE, GRAY, RED, RED]
ran = random(0.01,0.1)
coorX = int(random(-100,100))
coorY = int(random(-100,100))
coorZ = int(random(-200,200))
forms.push(new Shape(coorX, coorY, coorZ));
}
function draw() {
background(80);
pointLight(250, 250, 250, 250);
for(let i = 0; i < forms.length-1; i++) {
newSpeed = 0.05 + i * ran
forms[i].show(newSpeed, 0.01);
}
forms[forms.length-1].rotate(2.5, 0.01);
if (forms.length > 10){
//Array limited on 10 objects
forms.splice(0,1)
}
}
function keyTyped() {
if (key === 'a'){
coorX = int(random(-100,100))
coorY = int(random(-100,100))
coorZ = int(random(-200,200))
forms.push(new Shape(coorX, coorY, coorZ));
}
if (key === 'd'){
forms.pop()
}
}
class Shape {
constructor(posX, posY, posZ, colour){
this.posX = posX;
this.posY = posY;
this.posZ = posZ;
this.rand = int(random(0,5));
this.colour = colour;
this.lastActiveFrame = frameCount;
}
rotate(speed, rotation){
//create a new shape
stroke(0);
strokeWeight(0);
push();
translate(this.posX, this.posY, this.posZ)
//rotate the shape
this.lastActiveFrame = frameCount;
rotateX(frameCount * rotation * speed)
rotateY(frameCount * rotation * speed)
if (this.rand == 1){
fill(RED)
box(50,50,50)
}if(this.rand == 2) {
fill(LIGHTGRAY);
sphere(50,10)
}if(this.rand == 3){
fill(WHITE);
cylinder(5,280,15)
}if(this.rand == 4){
fill(GRAY);
torus(90,24,3)
}
pop();
}
show(speed, rotation){
//create a new shape
stroke(0);
strokeWeight(0);
push();
translate(this.posX, this.posY, this.posZ)
//rotate the shape
rotateX(this.lastActiveFrame * rotation * speed)
rotateY(this.lastActiveFrame * rotation * speed)
if (this.rand == 1){
fill(RED)
box(50,50,50)
}if(this.rand == 2) {
fill(LIGHTGRAY);
sphere(50,10)
}if(this.rand == 3){
fill(WHITE);
cylinder(5,280,15)
}if(this.rand == 4){
fill(GRAY);
torus(90,24,3)
}
pop();
}
}
In the console, p5.js says that the 4th argument of pointLight() must be a Vector. That argument is used to tell in which direction the light will point, as for the arguments 1 - 3, they tell where is the pointLight.
Vector reference
pointLight reference

Scrolling through an array

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

Efficiently navigating arrays and selected strings

I am a noob playing around with actionscript but i feel this question is a basic coding questionMy project is similar to this picture.
I have four quadrant areas (Red, blue, yellow, and green) that I am adding text buttons to each area with a single word in each button. There are 16 words in each section that are added from 4 arrays that have the preset words (redWordArray, greenWordArray, yellowWordArray, blueWordArray). When clicked, the text button glows using a glow filter and the word gets added to another array for data collecting. For instance, a red word when clicked gets added to a red array (redChosenArray). When the word is clicked again, it removes the glow filter and is removed from the chosen array.
I am finding that my performance is slow and I am wondering if I am adding and deleting words correctly and efficiently. These are my functions for adding the glow filters and the selected word to the array. I would love your insights for best coding practices as I am sure it is a mess!
Thank you!
function selectWord(event:MouseEvent):void
{
var tempWord:String = event.currentTarget.mood.text;
var tempArray:Array;
if (event.currentTarget.clicked == false)
{
event.currentTarget.filters = filterArray;
event.currentTarget.clicked = true;
tempArray = addToArray(tempWord)
tempArray.push(tempWord);
trace(redChosen);
trace(blueChosen);
trace(yellowChosen);
trace(greenChosen);
trace("");
}else if(event.currentTarget.clicked == true)
{
event.currentTarget.filters = emptyFilterArray;
event.currentTarget.clicked = false;
removeMoodWord(tempWord);
trace(redChosen);
trace(blueChosen);
trace(yellowChosen);
trace(greenChosen);
trace("");
}
}
function addToArray(moodWord:String):Array
{
var wordFound:Boolean = false;
var allWords:int = 16;
var chosenArray:Array;
while (!wordFound)
{
for (var h:int = 0; h < allWords; h++)
{
if (moodWord == redWords[h])
{
chosenArray = redChosen;
wordFound = true;
}else if (moodWord == yellowWords[h])
{
chosenArray = yellowChosen
wordFound = true;
}else if (moodWord == greenWords[h])
{
chosenArray = greenChosen
wordFound = true;
}else if (moodWord == blueWords[h])
{
chosenArray = blueChosen
wordFound = true;
}
}
}
return chosenArray;
}
function removeMoodWord(moodWord:String):void
{
if (redChosen.indexOf(moodWord) >= 0)
{
redChosen.splice(redChosen.indexOf(moodWord), 1);
}else if (blueChosen.indexOf(moodWord) >= 0)
{
blueChosen.splice(blueChosen.indexOf(moodWord), 1);
}else if (yellowChosen.indexOf(moodWord) >= 0)
{
yellowChosen.splice(yellowChosen.indexOf(moodWord), 1);
}else if (greenChosen.indexOf(moodWord) >= 0)
{
greenChosen.splice(greenChosen.indexOf(moodWord), 1);
}
i fee}

How to assign value to Numbers in Array?

Hey everyone so I have an Array private var frames:Array; which I give value and initiate in my constructor function like so frames = [2, 3, 4, 5, 6, 7, 8];
Now I am trying to give a string value to each number in the array for my hitTest Function. I was thinking something on the lines of a for loop and giving them values there but having some issues here is what I have so far:
for (var i:int = 0; i < frames.length; i++)
{
var currentFrameNumber = frames[i];
//assign values to numbers in array
if (currentFrameNumber == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (currentFrameNumber == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (currentFrameNumber == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (currentFrameNumber == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (currentFrameNumber == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (currentFrameNumber == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (currentFrameNumber == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
this doesn't work at all. I know I Am missing something crucial. Please any help would be appreciated thanks!
****************UPDATE****************
I have my array of Movie clips like so aClockArray = [playScreen.wire_5, playScreen.wire_6, playScreen.wire_7, playScreen.wire_8];
in my last post I finally figure out how to randomize the array with no repeat like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
//nWire = randomNumber(2, 8);
currentWires.gotoAndStop(randomFrame);
}
and above in my frames for loop is where I assign the values to the numbers in the frames array for my hitTest which I try to accomplish like so:
private function wireHitTestFunction():void
{
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
if (redCopper.hitTestObject(currentWires) && currentWires.sRed == "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.sBlue == "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}
I cant seem to figure this out lost in code haha. I probably have it set up really badly.
basically the game is I have 7 colored wires on the stage that the user can drag and place inside the correct color slot. It was working fine until I had added the var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1); I had to change things around. It was working fine when my original code was like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
//var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
nWire = randomNumber(2, 8);
currentWires.gotoAndStop(nWire);
//If any of the Wires lands on 2,3,etc.. Assign Color for Hit Test
if (nWire == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (nWire == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (nWire == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (nWire == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (nWire == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (nWire == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (nWire == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
I'm not sure exactly what issue you're seeing, and it's hard to know exactly what's going on without seeing the entire code, but I'll take a stab at it...
rather than currentWire.sRed = "RED";
use a single variable to represent the current color, like so:
currentWire.color = "RED";
then..
if (redCopper.hitTestObject(currentWires) && currentWires.color== "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.color== "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}

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