Friday, January 27, 2012

Frustration

Another day of frustration in working on the project. I still have not been able to figure out how to fix the problem of changing the text on the buttons for the dice, even with a couple hours of googling for anything that would be helpful. I did find a lot of very interesting stuff about panda, stuff that will probably come in useful if I ever try to make something else, but not really anything that'll help me out right now. So I also started working on just making the buttons so that they don't have changing text and each button is equal to one die and clicking the button keeps the die out of the roll, but no luck there either. For some reason, the buttons aren't even showing up on the page. I wonder if I'm putting it in the wrong place in the code. Or maybe I'm not inserting them into the render2d branch of the scene graph correctly. Time to do some more googling.

I also spent a good chunk of time working on the final paper for the project. I've got an outline made, and I've started writing the paper proper, so I should have it done easily by Monday. Something else to get started on over the weekend is the powerpoint and what I'm going to say for the presentation on Wednesday. Need to check the date on that, maybe it was Tuesday.

Thursday, January 26, 2012

Dental Work

So I had some dental work done this afternoon, and what with working a job in the morning to early afternoon, I didn't get much work done on the project. Not to worry though, I've got a chunk of free time set aside this weekend to make up the time lost having someone take a drill to my teeth. I did make one significant piece of progress though. I figured out exactly what was going wrong with the error I was having trouble with the last couple of days. When I called the setText function on a set die, I was calling it as self.die1.setText("1"). The error said that I was trying to pass the function two arguments, which I didn't think I was doing. Well, apparently I was passing it two arguments without realizing it. When a function is called with the dot operator, the object the function is called on is passed to the function as an argument. So when I called self.die1.setText("1"), what this actually translated to was die1.setText(self, "1"), which is two arguments. I haven't been able to fix this problem yet, because taking out the self doesn't work since I'm calling the function in a separate function from the function in which I declared the objects. So the interpreter doesn't know what die1 is unless I tell it is a member of self. So I may end up having to declare the die buttons to be globals that can be accessed from any function in the program. I tried implementing it that way, but since I have little experience in globals, I was doing something wrong and it wasn't working. Globals tend to be pretty dangerous, since you could easily change the value accidentally in a function that shouldn't have access to the variables, so they tend not to get taught much in programming classes and I never learned how to implement them before. Another thing on my to-do list for this project is to get to work finishing up my final paper. I'll finish up work on that over the weekend, also in that free time I've got planned out.

Wednesday, January 25, 2012

Frustrated

So I really made next to no progress today. I'm trying to get buttons added to the page with the values of the dice on them. When you click on a button, it keeps that die out of the next roll. The problem I am having is setting the number on the buttons. I created the buttons with blank text, later when the dice have been rolled, the program goes back and changes the text to the value of the die. I get an error back when I try to change that text and I don't know why. I try to call the standard setText("1") on the button object, and it tells me that the function setText can only accept one argument and I am passing it two. I don't know what to do with this error, as I am obviously only passing the function one argument. This is exactly like the code that the user manual has, when it tells you how to change the text of the button. So the next step for me is going to be one of two things. I'm going to try googling around and see if someone else has ever had the same problem I'm having. In programming this helps more often than not. Another thing I might try is to just have the buttons go to specific dice and not bother changing the text for right now. So I can get that working and keep the dice out, and later, when I've learned more about the engine, I can go back and add the functionality to say exactly what the values of the dice are. It's been a very frustrating day overall.

Tuesday, January 24, 2012

Know the dice, Be the dice

Today, I managed to get the program to recognize what numbers the dice have been rolled to. The screenshot below shows what I've accomplished. It doesn't look like much, but the numbers at the bottom of the screen are the values of the dice that have been rolled. Before, the program could only throw a few cubes around, but I was able to get the program to recognize that each side has a number, and to recognize when that side is face up. From here, I could easily add Yahtzee like scoring to it, but with the program as it is, I could only roll once and hope to get something good. Next, will be adding the functionality of picking dice and keeping those from being rolled in the next roll. From there, it should be simple to create a Yahtzee game. The code snippet below is the function that calculates the orientation of the die and appends a number to the diceValues list based on which face is pointing up.


diceValues = []
for d in self.winlist.keys():
            l, m, n = self.winlist[d]
            a = int(l+0.5)
            b = int(m+0.5)
            c = int(n+0.5)
            if b == 0 and c == -89:
               diceValues.append(1)
            elif b == 0 and c == 0:
               diceValues.append(2)
            elif b == 90:
               diceValues.append(3)
            elif b < -88:
               diceValues.append(4)
            elif b == 0 and c != 90:
               diceValues.append(5)
            elif b == 0 and c == 90:
               diceValues.append(6)

Monday, January 23, 2012

Another day

So I have decided to use the render2d to show the values of the dice on the side of the screen. I'm having some difficulty getting that to work however. I should be able to get it done tomorrow. I'm growing concerned about screen space in my final game. There is a lot of information to be displayed on the screen, and I don't know how all of it is going to fit in. I'm going to look into upping the size of the window and/or getting a higher resolution going. There's going to be a model of the monster(s) in the encounter, plus all four of the player's characters and their abilities, plus the rolling dice, plus the dice values that can be selected. I'm thinking the monster is going to basically replace the back wall of the "room" that the dice are being thrown in, but that doesn't really leave a lot of room for everything else. Anyway, here's a few pieces of my code:

Here's a couple functions that are used to rotate the dice randomly when the game is first started, to give the cool floating effect.

    # spin the models randomly
    def rotateModels(self, task):
        self.frame = self.frame + 1
        if self.frame >= FRAMESKIP:
           self.frame = 0
           for die in self.dice:
               x = random.randint(0,359)
               y = random.randint(0,359)
               z = random.randint(0,359)
               die[0].setHpr(x,y,z)
               die[3].setPosition(die[0].getPos(render))
               die[3].setQuaternion(die[0].getQuat(render))
        if self.collision == False:
           return Task.cont
        else:
           return Task.done

    # start the dice rotating
    def startRotation(self):
        if self.rotationRunning == False:
           self.rotationRunning = True
           self.inSimulation = False
           self.taskMgr.add(self.rotateModels, "rotateModels")


This function is the dice throw. It comes up with a random direction to throw the dice, that is always directed upwards. Notice that this is done by setting a force to work on the object. It is very nice how panda provides a function like this, instead of me having to program in some complicated function with a whole bunch of physics that I have probably forgotten since I took physics.
    # force (explode) the dice
    def forceDie(self):
        for i in range(0,7):
            body = self.dice[i][3]
            a = random.randint(-17000000,17000000)
            b = random.randint(-17000000,17000000)
            c = random.randint(10000000,33000000) # up is always big to overcome gravity
            body.setForce(Vec3(a, b, c))

Sunday, January 22, 2012

Breakthrough on 3d dice

So Friday and Saturday, I made a breakthrough on my Yahtzee game. I found a tutorial online that went over creating 3-dimensional dice and I combined that with a 3d room I had created earlier when I was learning how to use panda3d. So I ended up with a very cool looking view of a stone room with dice floating around. I put a button at the bottom of the screen that acts as a throw button. The button is also an image of one of the dice being thrown, so when the dice are in the air, you get a very cool rotating 3d model of a die in the corner of the screen. There's a video below of what I've got so far. The next step in this is making the player able to pick dice to keep out and not throw the next time the dice are rolled. For that, I'm going to have to include some code that was written for my Senet game. That code has functions for allowing the mouse to select an object in the 3-dimensional space with the 2-dimensional pointer and screen. Since the only element of the dice game I have at present is the throw button, and it is in the render2d library, the functions already in it for clicking will not work for clicking on the dice in the window. An alternative solution, that I may try, is to keep a display on the side of the screen that shows the current dice values. That way the part that is to be selected with the mouse would remain in the render2d library and new functions could be kept to a minimum. I'll have to decide which of the two options would be preferable based on user interface design and coding feasibility. The code is a bit too long to paste any in here. On Monday, once it has been cleaned up a bit, I'll either post segments of it, or provide a link to download the entire file.