So i'm kinda stuck on somethng.
i kinda want a random drop wen i kill my monster.
this is what i got.
i've got a weapon1
class weapon {
var str = Int
}
class Weapon1: weapon {
override init() {
super.init()
str = 10
}
class Weapon2: weapon {
override init() {
super.init()
str = 20
}
i've got a monster
class monster {
str = 20
def = 10
drops = [weapon1(), Weapon2()]
}
and i have a place to link my drops to if my monster is death
var itemdrops = weapon()
and when my monster dies it should link my monster drop to my itemdrops..
so i can use it somewhere like in an inventory.
but when i try to do it like this
random = (arc4random_uniform(UInt32(monster.items.count-1)))
//-1 becous it would say 2 items and an array starts at 0
itemdrops = monster.items[random]
but then items is in white..
The problem is that items is an instance property of monster:
class monster {
str = 20
def = 10
drops = [weapon1(), Weapon2()]
}
But when you try to access it, you try to access it through the class:
monster.items[random]
The class monster has no class/static property items, so your code cannot compile.
This is a good reason for using capital letters for class names, as you are supposed to. It helps you keep track of whether this thing is a class or an instance. Example:
class Monster {
str = 20
def = 10
drops = [Weapon1(), Weapon2()] // assume you've named these classes correctly
}
Now, in your code, you would say:
let aMonster = Monster() // an _instance_
var itemdrops = aMonster.items[random]
Related
I have developed a small Swift code that displays somebody's total likes. So I have one code based on a while loop to add up the amount of likes into one total. Then, I created a function that displays a short phrase including the result of that loop. Now, in my view controller I want to run that display function on a label I have created to finally display the all time likes on the screen. However, I can't seem to understand how I should run the display function on the label and have it display without it being a result of me clicking a button first. Keep in mind, this is my second day of coding, with only prior experience in the basic syntax of Java.
Here is the first code
import UIKit
class likesObject: NSObject {
// This is where I created the loop to solve for the total amount of likes
func complimentsLikeTotal() -> Void {
let monthlyLikes = [20, 15, 13, 32, 14, 38]
var totalLikes = 0
var runTotal = 0
while runTotal < monthlyLikes.count {
totalLikes += monthlyLikes[runTotal]
print(totalLikes)
runTotal += 1
}
}
/*
This is where I created the function to return how many all time likes there are in a phrase
I want to use this function in the viewcontroller code on the label
*/
func display() -> String {
return "\(complimentsLikeTotal) all time likes"
}
}
Here is the view controller code
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var inputLikesLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Here is where I don't know what to do with display and how to link it with the label
self.inputLikesLabel.text = display
}
}
Probably looking for something like this: (please make the class name start with capital as per convention)
var likesObject = LikesObject()
likesObject.complimentsLikeTotal()
let display = likesObject.display()
self.inputLikesLabel.text = display
I assume that the LikesObject class also has some global variables defined to hold the data.
P.s. in swift it is not necessary to explicitly state void return value, if you omit it the compiler implies void.
Is it possible to add subclassed objects to a static array inside the parent class? I would like to run a function on all instances created. Another SO question describes being able to loop over an array to call a function on each instance and I think this is the end result I would like as well but my problem is even getting the instances into a static array that keeps track of all instances.
Of course my code is more modular but here is a simplified view of the code and hierarchy:
class Jungle {
static var jungle: [Animals] = []
}
class Tigers: Animals {
static var tigerPopulation: Int = 0
override init(name:String){
super.init(name: name)
Tigers.tigerPopulation += 1
}
deinit {
Tigers.tigerPopulation -= 1
}
}
class Monkeys: Animals {
static var monkeysPopulation: Int = 0
override init(name: String){
super.init(name: name)
Monkeys.monkeysPopulation += 1
}
deinit {
Monkeys.monkeysPopulation -= 1
}
}
class Snakes: Animals {
static var snakePopulation: Int = 0
override init(name: String){
super.init(name: name)
Snakes.snakePopulation += 1
}
deinit {
Snakes.snakePopulation -= 1
}
}
I get the feeling that I should have created the Jungle class first so they all would subclass from Jungle I guess but I'm still stumped on how I would get the instances into an array.
Instead of trying to trigger some behavior to increase the monkey count, tiger count etc from within an initializer, it will be easer to just add everything to an animals array, and then use the animals array to figure out how many Tigers/Snakes/Monkeys there are.
Basing the count off that single array is going to be easier in the long term than having a bunch of different variables, and making sure they're in sync (e.g. by decreasing during deinit).
Here's a minor reshuffle of your jungle, animal, and animal subclasses:
class Jungle {
var animals: [Animal] = []
func addAnimal(animal: Animal) {
animals.append(animal)
}
// this is a computed property, everytime you access it
// via jungle.tigerPopulation, the code inside this statement
// executes, and you get the value that is returned
var tigerPopulation: Int {
// tigers is a new array containing only tigers
let tigers = animals.filter{ animal in
return animal is Tiger
}
// return the number of items in the tigers array
return tigers.count
}
}
class Animal {
let name: String
init(name: String) {
self.name = name
}
func sayHello() {
print("I'm an animal")
}
}
class Tiger: Animal {
// tiger specific stuff
override func sayHello() {
print("I'm a tiger called", name)
}
}
class Monkey: Animal {
// monkey specific stuff
}
class Snake: Animal {
// snake specific stuff
override func sayHello() {
print("I'm a snake called", name)
}
}
Something to point out is that because each of the animal subclasses are currently doing the same thing (assigning the name) you don't need to override the initializer in the subclasses - that's the value of class inheritance!
You can override the subclasses sometimes in the future if an animal has to do something that's different from other animals.
The most interesting thing that's happening here is the computed property that calculates the tiger population by filtering the tigers in the animals array, and returning the count, this way you're not manually +/- 1 the population count, but just calculating it whenever you ask for it.
Then you'd use your jungle object something like this:
let jungle = Jungle()
// jungle.animals -> []
// jungle.animals.count -> 0
// jungle.tigerPopulation -> 0
jungle.addAnimal(animal: Tiger(name: "Tony"))
// jungle.animals -> [Tiger()]
// jungle.animals.count -> 1
// jungle.tigerPopulation -> 1
jungle.addAnimal(animal: Snake(name: "Susan"))
// jungle.animals -> [Tiger(), Snake()]
// jungle.animals.count -> 2
// jungle.tigerPopulation -> 1
for animal in jungle.animals {
animal.sayHello()
}
// prints ->
// I'm a tiger called Tony
// I'm a snake called Susan
I am very new to this and hoping it's something that should have been obvious.
When I run the code below, the Array newHole and newArray both return 1 on the trace. Originally the code was built with only the newHole array, but I created the newArray in the hopes of troubleshooting. It did not help. The class for bulletHole contains no extra code so I didn't post that.
Thank you.
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
Mouse.hide();
var myReticle:MovieClip;
var holeArray:Array = new Array();
var randomHole:Number = randomNumber(1, 5);
var newHole:bulletHole = new bulletHole();
var newArray:Array = new Array();
stage.addEventListener(MouseEvent.MOUSE_MOVE, followReticle);
stage.addEventListener(MouseEvent.CLICK, myFire);
stage.addEventListener(MouseEvent.CLICK, checkCount);
function followReticle(event:MouseEvent):void
{
myReticle.x = mouseX;
myReticle.y = mouseY;
}
function myFire(int):void
{
stage.addChild(newHole);
newHole.x = myReticle.x;
newHole.y = myReticle.y;
//holeArray.push(newHole);
newHole.gotoAndStop(randomHole);
//trace(holeArray.length);
}
function checkCount(int):void
{
newArray.push("A");
trace(newArray.length);
}
function randomNumber(low:Number=0, high:Number=1):Number
{
return Math.floor(Math.random() * (1+high-low)) + low;
}
Most likely the issue is that the code you've posted is running over and over again. In other words, you have a looping timeline that eventually goes back to the frame that the code you've shown is on.
Whenever that frame is reached, you have the following:
var holeArray:Array = new Array();
Which creates a new array replacing what used to be in that var.
To solve this, you either need to:
take the code out of the timeline (put it in a class file and attach that as the document class of your project)
re-architect your timeline so the first frame is only reached 1 time
put some checks in so that the code only runs the first time the frame is reached.
Here is an example of the latter option:
//just define the array, don't create it
var holeArray:Array;
//if the array is null, create it (it will only be null the first time this code is run
if(!holeArray){
holeArray = new Array();
}
This line is incorrect:
function myFire(int):void {
Because the function is triggered from a mouse event listener it should read:
function myFire(e:MouseEvent):void {
What you are doing is passing a undefined int to the function. Hope this helps.
EDIT: You should delete the clickCount event listener and function as they're not needed.
Also notice that you should move this line to the top of your myFire function or else you will keep replacing this MovieClip instead of creating it again:
var newHole:bulletHole = new bulletHole();
I am trying to create an array that will store my class objects. The createEnemies method is called when a level is started. Which should then create the enemy objects. However I don't understand how to do that. It should be created after "if(levelNumber < 5)"
class level {
class func createEnemies() {
numEnemies = Int(floor(levelNumber * 1.5 + 10))
println("Number of Enemies this level: \(numEnemies)")
if(levelNumber < 5){
//Create numEnemies amount of class objects
}
}
}
//Enemy Variables
var enemiesKilled = 0
class enemy {
class func enemiesKilled() {
}
class standard {
var health:Int = 10
var name:String = "Standard"
var worth:Int = 10
var power:Int = 10
init () {
}
func kill() {
}
func damage(damage: Int) {
self.health -= damage
println("\(self.name) was damaged \(damage)")
if(self.health <= 0){
self.kill()
}
}
}
For Swift 3.1
var enemies:[enemy] = [enemy]()
Create an array of elements of a custom class like this:
var enemies = [enemy]()
You can add elements to it like this:
enemies.append(anEnemy: enemy)
If you want to have a specific number of enemies in the array there are several ways to achieve this (I write Enemy instead of enemy because the first letter of a class name is usually uppercase):
// "old fashioned" for loop
var enemies = [Enemy]()
for _ in 1...numEnemies {
// call initializer of Enemy
enemies.append(Enemy())
}
// my personal preference (Range has a method named map which does the same as Array)
// without the "_" you could also access the numbers if you want
let enemies = (1...numElements).map{ _ in Enemy() }
If you need to access the array later on you should declare the variable under your comment //Enemy Variables.
Let's say I have an array, each item in the array has a corresponding library item.
I'd like to do something like :
var rando = Math.round(Math.random()*3)
var myArray = new Array ["ball", "wall", "fall"]
var i:myArray[rando] = myArray[rando] new myArray[rando]()
addChild(i)
But, this doesn't work. What's the secret?
Thank You,
Victor Hugo
Surprised no one mentioned getDefinitionByName() here.
Here's some complete code to get your example working:
var myArray = ["ball", "wall", "fall"];
/**
* Creates a random instance based on an input array containing class names as Strings.
* #param The input array containing aforementioned Strings.
* #return The newly created instance.
*/
function createRandom(typeArray:Array):*
{
// Select random String from typeArray.
var selection:String = typeArray[ int(Math.random() * typeArray.length) ];
// Create instance of relevant class.
var Type:Class = getDefinitionByName(selection) as Class;
// Return created instance.
return new Type();
}
// Randomly create and add instance.
var instance:DisplayObject = createRandom(myArray);
addChild(instance);
Ok so there are a bunch of problems with this.
A large one being var i:myArray[rando] = myArray[rando] new myArray[rando]() not really too sure what you're trying to do here.
Anyway I'm going to assume ball, wall and fall are instance names of MovieClips you have in your library. I think you're going to want something like this
var rando:int = Math.floor(Math.random()*3); //As the comments point out this should give you a random
//int between 0 and 2, arrays are 0 indexed so this is what we want if we have 3 items
Now for your array, you're current putting strings in there. Flash has no idea what "ball", etc are.
Try something like this
var myArray:Array = new Array [new ball(), new wall(), new fall()]; //this creates a new instance of your library object and stores it in your array
Now to add one of these to your stage:
addChild(myArray[rando]); //this uses the random number to pull one of the items out of your array
What you're trying to do with var i:myArray[rando] doesn't really make sense. There is no type of myArray[rando] this slot should be holding a MovieClip
If you only have a few choices, it's easier to use a switch-case.
switch (rando) {
case 0:
i = new ball();
break;
case 1:
i = new wall();
break;
case 2:
i = new fall();
break;
}
addChild(i);
I suggest you define the variable i as a MovieClip, in which case it can be instantiated as both ball, wall, fall.
Given that ball, wall and fall are in the library exported to actionscript.
Just guessing off your limited information but give this a shot.
private function myFunction():void{
var rando = Math.round(Math.random()*3);
var myArray= new Array ["ball", "wall", "fall"];
}
private function generateItem(item:String):void{
switch(item){
case "ball" : generateBall(); break;
case "wall" : generateWall(); break;
case "fall" : generateFall(); break;
}
private function generateBall():void{
//code to generate ball
addChild(ball);
}
private function generateFall():void{
//code to generate fall
addChild(fall);
}
private function generateWall():void{
//code to generate wall
addChild(wall);
}
Change your arrary line to:
var myArray = new Array [ball, wall, fall];
This should work. :)
Marty Wallace gets big praise for steering me down the path of getDefinitionByName(). The example he posted was good, but this example does exactly what I was going for.
http://www.emanueleferonato.com/2011/03/31/understanding-as3-getdefinitionbyname-for-all-eval-maniacs/